补充:
1、TCP通信采用一对一的通信模式。日常生活中的网络会议通知、广告、网络信息公告等功能,需要采用UDP实现一对多的群发功能。
通过Internet实现群发功能的形式有两种:
(1)利用广播向子网中的所有客户发送消息,比如各类通知、单位公告、集体活动日程安排等:
(2)利用组播向Internet网上不同的子网发送消息,比如集团向其所属的公司或用户子网发布信息公告等。
广播,就是想对局域网内所有的主机同时发送数据,但是广播还是要指明接收者的端口号的,因为不可能接受者的所有端口都来收听广播。广播IP地址:192168.1.255/1921681(-1)广播MAC 地址:255.255255.255
2、广播的特点:子网中未参加相应广播应用的所有主机都会受到广播影响。
3、向一个广播地址发送UDP数据报时所发生的步骤为:
首先假设子网地址为192.168.34,该子网的广播地址为192168.34.255,此子网下有俩台IP地址分别为192.168.341和192168.34.2的主机
(1)广播时sendto向IP为192168.34.255端口为3333发送数据报,此IP数据报在以太网下会激活ARP将目的广播地址192.168.34.255映射成相应的以太网地址(物理地址),然后将目的地址为此地址的帧发出去
(2)这次IP为192168.341和192168342的主机接口都会和此广播地址匹配成功,直到该数据报进入UDP层时根据端口是否匹配才判断是否丢弃该数据,端口为3333的会保留该数据,否则将数据丢弃。
4、广播:根据定义,广播分组会去往子网上的所有主机,包括发送主机自身,广播的缺点:未参加广播的主机也会受到影响
5、关于setsockopt
int setsockopt(int sockfd , int level, int optname, void *optval, socklen_t *optlen);
函数功能:设置套接字描述符的属性。
参数:
sockfd:要设置的套接字描述符。
level:选项定义的层次。或为特定协议的代码(如IPv4,IPv6,TCP,SCTP),或为通用套接字代码(SOL_SOCKET)。
optname:选项名。level对应的选项,一个level对应多个选项,不同选项对应不同功能。
optval:指向某个变量的指针,该变量是要设置新值的缓冲区。可以是一个结构体,也可以是普通变量
(参数optval表示选项的值,是一个指向选项值的指针。具体来说,它的类型和长度与所设置的选项有关,不同的选项可能需要不同类型和长度的参数。下面举例说明几种常见的选项及其对应的optval参数:
-
SO_REUSEADDR选项:用于允许重用本地地址,其optval参数类型为int,表示是否允许重用地址,通常取值为1或0。
-
SO_KEEPALIVE选项:用于启用TCP的心跳机制,其optval参数类型为int,表示是否启用心跳机制,通常取值为1或0。
-
TCP_NODELAY选项:用于禁用Nagle算法,其optval参数类型为int,表示是否禁用Nagle算法,通常取值为1或0。
-
SO_SNDBUF和SO_RCVBUF选项:用于设置发送和接收缓冲区的大小,其optval参数类型为int,表示缓冲区的大小,单位为字节。)
optlen:optval的长度。
一、通信框架
二、示例代码
recv端
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<sys/msg.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<fcntl.h>
#include<sys/stat.h>
int main()
{
int recv_fd;
struct sockaddr_in recv_addr,send_addr;
socklen_t recv_len,send_len;
char rdBuffer[64] = {0};
recv_fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if(recv_fd < 0)
{
perror("socket failed\n");
exit(1);
}
printf("recv_fd:%d\n",recv_fd);
recv_addr.sin_family = AF_INET;
recv_addr.sin_port = htons(8090);//设定一个服务器的端口号
recv_addr.sin_addr.s_addr =htons(INADDR_ANY);
recv_len = sizeof(recv_addr);
send_len = sizeof(send_addr);
bind(recv_fd,(struct sockaddr *)&recv_addr,recv_len);
while(1)
{
recvfrom(recv_fd,rdBuffer,64,0,(struct sockaddr *)&send_addr,&send_len);
printf("%s\n",rdBuffer);
}
printf("recv over\n");
close(recv_fd);
return 0;
}
send端
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
struct sockaddr_in broadcast_addr = {0};
int send_fd;
socklen_t broadcast_len;
char rdBuffer[64] = {0};
send_fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if(send_fd < 0)
{
perror("socket failed\n");
exit(1);
}
printf("send_fd:%d\n",send_fd);
int on = 1;
setsockopt(send_fd,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on));//允许发送广播数据包
broadcast_addr.sin_family = AF_INET;
broadcast_addr.sin_port = htons(8090);
broadcast_addr.sin_addr.s_addr = inet_addr("192.168.56.255");
broadcast_len = sizeof(broadcast_addr);
int i = 5;
while(i--)
{
sendto(send_fd,"helloworld",12,0,(struct sockaddr *)&broadcast_addr,broadcast_len);
sleep(2);
}
close(send_fd);
return 0;
}
四、结果
五、参考文献文章来源:https://www.toymoban.com/news/detail-753791.html
(63条消息) setsockopt()函数详解_Linux冰岛的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-753791.html
到了这里,关于UDP的一对多通信(广播)-----个人笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!