UDP广播

devtools/2024/10/24 5:08:01/

1、UDP广播

1.1、广播的概念

广播:由一台主机向该主机所在子网内的所有主机发送数据的方式

例如 :192.168.3.103主机发送广播信息,则192.168.3.1~192.168.3.254所有主机都可以接收到数据

广播只能用UDP或原始IP实现,不能用TCP

1.2、广播的用途

单个服务器与多个客户主机通信时减少分组流通 以下几个协议都用到广播

1、地址解析协议(ARP)

2、动态主机配置协议(DHCP)

3、网络时间协议(NTP)

1.3、广播的特点

  1. 同一子网内的所有主机都必须处理接收到的数据。这意味着当一台主机发送广播信息时,子网内的所有其他主机都将接收并处理该数据,无论它们是否需要该信息。
  2. 由于广播只能通过UDP或原始IP实现,因此UDP数据包会沿着协议栈向上传输,直到到达UDP层。这与TCP不同,TCP数据包在传输过程中会经过更多的协议层处理。
  3. 运行音频、视频等高速率应用时,广播通信可能会带来较大的负载。这是因为所有主机都必须处理接收到的数据,即使它们并不需要这些数据。这可能会导致网络拥塞和性能下降。
  4. 广播通信通常局限于局域网(LAN)内使用。这是因为广播信息会被发送到子网内的所有主机,而不同子网之间的通信通常需要使用其他网络协议,如单播或多播。

1.4、广播地址

{网络ID,主机ID}

网络ID表示由子网掩码中1覆盖的连续位

主机ID表示由子网掩码中0覆盖的连续位

定向广播地址:主机ID全1

1、例:对于192.168.220.0/24,其定向广播地址为192.168.220.255 2、通常路由器不转发该广播

受限广播地址:255.255.255.255

路由器从不转发该广播

2 、广播与单播的对比

单播

 广播

3 、广播流程 

  1. 创建套接字:使用socket()函数创建一个数据报套接字(SOCK_DGRAM),以支持UDP通信。
  2. 设置广播权限:使用setsockopt()函数将套接字设置为允许发送广播数据。这通常需要设置SO_BROADCAST选项。
  3. 发送数据:使用sendto()函数向广播地址发送数据。广播地址是一个特殊的IP地址,用于表示子网内的所有主机。例如,在IPv4中,广播地址通常表示为子网掩码全1的形式。

接收广播数据的步骤如下:

  1. 创建套接字:与发送者一样,使用socket()函数创建一个数据报套接字(SOCK_DGRAM)。
  2. 绑定套接字:使用bind()函数将套接字与一个本地地址和端口号绑定。这将使套接字能够接收发送到该地址和端口的数据。
  3. 接收数据:使用recvfrom()函数接收发送到绑定地址和端口的数据。该函数将返回发送者的信息,包括其IP地址和端口号。

4、套接字选项 

#include <sys/socket.h>int setsockopt(int socket, int level, int option_name,const void *option_value, socklen_t option_len);功能:设置一个套接字的选项(属性)参数:socket:文件描述符level:协议层次SOL_SOCKET 套接字层次IPPROTO_TCP tcp层次IPPROTO_IP IP层次option_name:选项的名称SO_BROADCAST 允许发送广播数据(SOL_SOCKET层次的)option_value:设置的选项的值int类型的值,存储的是bool的数据(1和0)0 不允许1 允许
option_len:option_value的长度返回值:成功:0失败:-1

 5、广播示例 

5.1 发送者

//广播发送者代码实现
#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h>
#include <sys/socket.h> //socket
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h> //htons inet_addr
#include <unistd.h> //close
#include <string.h>int main(int argc, char const *argv[])
{if(argc < 3){fprintf(stderr, "Usage: %s <ip> <port>\n", argv[0]);exit(1);}int sockfd; //文件描述符struct sockaddr_in broadcataddr; //服务器网络信息结构体socklen_t addrlen = sizeof(broadcataddr);//第一步:创建套接字if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){perror("fail to socket");exit(1);}//第二步:设置为允许发送广播权限int on = 1;if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0){perror("fail to setsockopt");exit(1);}//第三步:填充广播信息结构体broadcataddr.sin_family = AF_INET;broadcataddr.sin_addr.s_addr = inet_addr(argv[1]); //192.168.3.255 255.255.255.255broadcataddr.sin_port = htons(atoi(argv[2]));//第四步:进行通信char buf[128] = "";while(1){fgets(buf, sizeof(buf), stdin);buf[strlen(buf) - 1] = '\0';if(sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&broadcataddr, addrlen) < 0){perror("fail to sendto");exit(1);}}return 0;
}

5.2 接收者

#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h>
#include <sys/socket.h> //socket
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h> //htons inet_addr
#include <unistd.h> //close
#include <string.h>int main(int argc, char const *argv[])
{if(argc < 3){fprintf(stderr, "Usage: %s <ip> <port>\n", argv[0]);exit(1);}int sockfd; //文件描述符struct sockaddr_in broadcataddr; socklen_t addrlen = sizeof(broadcataddr);//第一步:创建套接字if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){perror("fail to socket");exit(1);}//第二步:填充广播信息结构体broadcataddr.sin_family = AF_INET;broadcataddr.sin_addr.s_addr = inet_addr(argv[1]); //192.168.3.255 255.255.255.255broadcataddr.sin_port = htons(atoi(argv[2]));//第三步:将套接字与广播信息结构体绑定if(bind(sockfd, (struct sockaddr *)&broadcataddr, addrlen) < 0){perror("fail to bind");exit(1);}//第四步:进行通信char text[32] = "";struct sockaddr_in sendaddr;while(1){if(recvfrom(sockfd, text, sizeof(text), 0, (struct sockaddr *)&sendaddr, &addrlen) < 0){perror("fail to recvfrom");exit(1);}printf("[%s - %d]: %s\n", inet_ntoa(sendaddr.sin_addr), ntohs(sendaddr.sin_port), text);}return 0;
}

执行结果


http://www.ppmy.cn/devtools/39342.html

相关文章

【Qt元对象系统解析】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 概述一、元对象系统二、信号与槽1.connect()函数的不同参数形式2. 使用 sender()获得信号发射者3. 自定义信号及其使用 概述 Qt实质上是一个跨平台的C开发类库&…

windows连接CentOS数据库或Tomcat报错,IP通的,端口正常监听

错误信息 数据库错误&#xff1a; ERROR 2003 (HY000): Cant connect to MySQL server on x.x.x.x (10060) Tomcat访问错误&#xff1a; 响应时间过长 ERR_CONNECTION_TIMED_OUT 基础排查工作 【以下以3306端口为例&#xff0c;对于8080端口来说操作是一样的&#xff0c;只需…

编译适配纯鸿蒙系统的ijkplayer中的ffmpeg库

目前bilibili官方的ijkplayer播放器&#xff0c;是只适配Android和IOS系统的。而华为接下来即将发布纯harmony系统&#xff0c;是否有基于harmony系统的ijkplayer可以使用呢&#xff1f; 鸿蒙版ijkplayer播放器是哪个&#xff0c;如何使用&#xff0c;这个问题&#xff0c;大家…

子比主题小黑屋列表

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么?二、使用步骤1.引入库前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文…

JavaScript 数组常用方法

JavaScript数组是一种用于存储多个值的有序集合。在JavaScript中&#xff0c;数组是一种特殊的对象&#xff0c;它具有一系列的方法&#xff0c;可以用来操作数组中的元素。下面详细说明一些常用的数组方法&#xff0c;并给出相应的代码案例。 push()方法&#xff1a;向数组的…

创建MySQL范围分区表详细指南

范围分区&#xff08;RANGE partitioning&#xff09;是MySQL中最常用的分区类型之一&#xff0c;适用于数据可以被分成连续范围的情况。此类型的分区非常适合处理时间序列数据&#xff0c;如按日期或年份分区。本文详细介绍如何在MySQL中创建范围分区表&#xff0c;包括设计考…

SpringBoot web项目性能监控

新增两个接口&#xff1a;jmap 和 jstack&#xff0c;用于获取 Java 应用程序的内存堆转储&#xff08;heap dump&#xff09;和线程转储&#xff08;thread dump&#xff09;。 添加依赖&#xff1a; implementation("commons-io:commons-io:2.11.0") 添加control…

keystone学习小结

1 keystone middleware 1.1 工作流程 middleware在客户端和服务端之间&#xff0c;会拦截客户端请求并判断请求身份是否是正确合法的&#xff0c;若是&#xff0c;则继续将请求发给其他middleware或app 具体看&#xff0c;干了这些事 1将请求里的auth header去除&#xff0c…