ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

组播和广播

组播和广播 1、网络属性网络套接字在不同层中有不同的设置分别有应用层套接字层、传输层、网络层、以太网层。对套接字属性进行设置可以使用setsockopt和getsockopt函数完成#includesys/types.h/* See NOTES */#includesys/socket.hintgetsockopt(intsockfd,intlevel,intoptname,void*optval,socklen_t*optlen);intsetsockopt(intsockfd,intlevel,intoptname,constvoid*optval,socklen_t optlen);功能设置或者获取套接字文件描述符的属性 参数1套接字文件描述符 参数2表示操作的套接字层 SOL_SOCKET:表示应用层或者套接字层通过man7socket进行查找 该层中常用的属性SO_REUSEADDR 地址快速重用 SO_BROADCAST 允许广播 SO_RCVTIMEOandSO_SNDTIMEO:发送或接收超时时间 IPPROTO_TCP:表示传输层的基于TCP的协议 IPPROTO_UDP:表示传输层中基于UDP的协议 IPPROTO_IP:表示网络层 该层常用的属性IP_ADD_MEMBERSHIP加入多播组 参数3:对应层中属性的名称 参数4参数3属性的值一般为int类型其他类型会给出 参数5参数4的大小 返回值成功返回0失败返回-1并置位错误码2、广播主机之间是一对多的通信方式网络对其中的每一台主机都会将消息进行转发在当前网络下的所有主机都会收到该消息无论是否愿意收到消息基于无连接的通信方式完成UDP通信广播分为发送端和接收端对于发送端而言需要设置允许广播并且向广播地址发送数据广播地址网络号 全为1的主机号可以通过指令 ifconfig查看广播消息不能穿过路由器到骨干路由上。广播发送到流程(类似于UDP的客户端)1、socket创建用于发送数据的套接字文件描述符2、setsockopt设置套接字属性允许广播 SOL_SOCKET层 中 SO_BROADCAST3、bind可以绑定也可以不绑定4、数据收发对端套接字地址信息结构体IP广播地址PORT与接收端保持一致5、sendto/recvfrom数据收发6、close关闭套接字#includestdio.h#includestdlib.h#includestring.h#includeunistd.h#includesys/socket.h#includenetinet/in.h#includearpa/inet.h#includeiostream// coutusingnamespacestd;// 可选不加就要写std::coutintmain(intargc,constchar*argv[]){//1、创建用于通信的客户端套接字文件描述符intsndfdsocket(AF_INET,SOCK_DGRAM,0);if(sndfd-1){perror(socket error);return-1;}printf(socket success cfd %d\n,sndfd);//3//设置允许广播intbroad1;//要设置的值if(setsockopt(sndfd,SOL_SOCKET,SO_BROADCAST,broad,sizeof(broad))-1){perror(setsockopt error);return-1;}printf(成功设置广播\n);//2、可以绑定也可以不绑定//3、数据收发charwbuf[128];//填充接收端的地址信息结构体structsockaddr_inrin;rin.sin_familyAF_INET;//通信域rin.sin_porthtons(8888);//端口号rin.sin_addr.s_addrinet_addr(192.168.174.255);//广播ip地址while(1){//清空容器bzero(wbuf,sizeof(wbuf));//从终端读取数据fgets(wbuf,sizeof(wbuf),stdin);wbuf[strlen(wbuf)-1]0;//将数据发送给服务器sendto(sndfd,wbuf,strlen(wbuf),0,(structsockaddr*)rin,sizeof(rin));printf(发送成功\n);}//4、关闭套接字close(sndfd);std::coutHello, World!std::endl;return0;}广播的接收端流程 (类似于UDP的服务器端)1、socket创建用于接收数据的套接字文件描述符2、bind必须绑定ip:广播地址PORT与发送端一致4、sendto/recvfrom数据收发5、close关闭套接字#includestdio.h#includestdlib.h#includestring.h#includeunistd.h#includesys/socket.h#includenetinet/in.h#includearpa/inet.h#includeiostreamintmain(intargc,constchar*argv[]){//1、创建用于通信的套接字文件描述符intrecvfdsocket(AF_INET,SOCK_DGRAM,0);//SOCK_DGRAM表示基于udp通信方式if(recvfd-1){perror(socket error);return-1;}printf(socket success sfd %d\n,recvfd);//3//2、绑定ip地址和端口号//2.1 填充要绑定的ip地址和端口号结构体structsockaddr_inrin;rin.sin_familyAF_INET;//通信域rin.sin_porthtons(8888);//端口号rin.sin_addr.s_addrinet_addr(192.168.174.255);//广播ip地址//2.2 绑定工作//参数1要被绑定的套接字文件描述符//参数2要绑定的地址信息结构体需要进行强制类型转换防止警告//参数3参数2的大小if(bind(recvfd,(structsockaddr*)rin,sizeof(rin))-1){perror(bind error);return-1;}printf(bind success\n);//3、数据收发charrbuf[128];//定义容器接收对端的地址信息结构体structsockaddr_incin;socklen_t socklensizeof(cin);while(1){//清空容器bzero(rbuf,sizeof(rbuf));//从客户端中读取消息if(recvfrom(recvfd,rbuf,sizeof(rbuf),0,(structsockaddr*)cin,socklen)-1){perror(recvfrom error);return-1;}printf([%s:%d]:%s\n,inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),rbuf);}//4、关闭套接字close(recvfd);std::coutHello, World!std::endl;return0;}3、组播广播是给同一个网络下的所有主机发送消息会占用大量的网络带宽影响正常网络通信造成网络拥塞组播也是实现一对多的通信机制也就是说加入同一个多播组的成员都能收到组播消息组播也是使用UDP实现的发送者发送的消息无论接收者愿不愿意都会收到消息组播地址D类网络地址 224.0.0.0 — 239.255.255.255组播的发送端流程 类似于UDP客户端1、socket:创建用于消息通信的套接字文件描述符2、bind非必须3、填充要发送的地址信息结构体IPD类网络PORT与接收端保持一致4、sendto发送数据5、close:关闭套接字#includestdio.h#includestdlib.h#includestring.h#includeunistd.h#includesys/socket.h#includenetinet/in.h#includearpa/inet.h#includeiostreamintmain(intargc,constchar*argv[]){//1、创建用于通信的客户端套接字文件描述符intsendfdsocket(AF_INET,SOCK_DGRAM,0);if(sendfd-1){perror(socket error);return-1;}printf(socket success cfd %d\n,sendfd);//3//2、绑定ip地址和端口号可选//3、数据收发charwbuf[128];//填充接收端的地址信息结构体structsockaddr_inrin;rin.sin_familyAF_INET;//通信域rin.sin_porthtons(8888);//端口号rin.sin_addr.s_addrinet_addr(224.1.2.3);//组播ip地址while(1){//清空容器bzero(wbuf,sizeof(wbuf));//从终端读取数据fgets(wbuf,sizeof(wbuf),stdin);wbuf[strlen(wbuf)-1]0;//将数据发送给服务器rsendto(sendfd,wbuf,strlen(wbuf),0,(structsockaddr*)rin,sizeof(rin));}//4、关闭套接字close(sendfd);std::coutHello, World!std::endl;return0;}组播的接收端流程 (类似于UDP服务器端)1、socket创建用于通信的套接字文件描述符2、setsocketopt设置套接字加入多播组 在IPPROTO_IP网络层 IP_ADD_MEMBERSHIP属性属性值为结构体类型struct ip_mreqn {struct in_addr imr_multiaddr; /* 组播地址的网络字节序/struct in_addr imr_address; /接收端的主机地址/int imr_ifindex; /网卡设备编号 一般为2 可以通过指令 ip ad 查看 */};3、bind绑定地址信息结构体IP组播地址PORT与发送端保持一致4、recv、recvfrom、read接收数据5、close:关闭套接字#includestdio.h#includestdlib.h#includestring.h#includeunistd.h#includesys/socket.h#includenetinet/in.h#includearpa/inet.h#includeiostreamintmain(intargc,constchar*argv[]){//1、创建用于通信的套接字文件描述符intrecvfdsocket(AF_INET,SOCK_DGRAM,0);//SOCK_DGRAM表示基于udp通信方式if(recvfd-1){perror(socket error);return-1;}printf(socket success sfd %d\n,recvfd);//3//将该套接字加入多播组structip_mreqnimr;//多播组属性结构体imr.imr_multiaddr.s_addrinet_addr(224.1.2.3);//组播地址imr.imr_address.s_addrinet_addr(192.168.174.128);//本机ip地址imr.imr_ifindex2;//网卡编号//调用设置网络属性函数if(setsockopt(recvfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,imr,sizeof(imr))-1){perror(setsockopt error);return-1;}printf(成功加入多播组\n);//2、绑定ip地址和端口号//2.1 填充要绑定的ip地址和端口号结构体structsockaddr_inrin;rin.sin_familyAF_INET;//通信域rin.sin_porthtons(8888);//端口号rin.sin_addr.s_addrinet_addr(224.1.2.3);//组播ip地址//2.2 绑定工作//参数1要被绑定的套接字文件描述符//参数2要绑定的地址信息结构体需要进行强制类型转换防止警告//参数3参数2的大小if(bind(recvfd,(structsockaddr*)rin,sizeof(rin))-1){perror(bind error);return-1;}printf(bind success\n);//3、数据收发charrbuf[128];while(1){//清空容器bzero(rbuf,sizeof(rbuf));//从客户端中读取消息if(recvfrom(recvfd,rbuf,sizeof(rbuf),0,NULL,NULL)-1){perror(recvfrom error);return-1;}printf([读取的消息为]:%s\n,rbuf);}//4、关闭套接字close(recvfd);std::coutHello, World!std::endl;return0;}
返回列表