在网站后台做网页,网站申请流程,wordpress消息系统,制作微信公众号的软件1、网络IP地址的分类
组播地址是分类编址的IPv4地址中的D类地址#xff0c;又叫多播地址#xff0c;他的前四位必须是1110#xff0c;所以网络地址的二进制取值范围是11100000~11101111对应的十进制为 224~~239。所以以224~239开头的网络地址都是组播地址。
组播地址的功能… 1、网络IP地址的分类
组播地址是分类编址的IPv4地址中的D类地址又叫多播地址他的前四位必须是1110所以网络地址的二进制取值范围是11100000~11101111对应的十进制为 224~~239。所以以224~239开头的网络地址都是组播地址。
组播地址的功能分类
224.0.0.0224.0.0.255为预留的组播地址永久组地址。
224.0.1.0224.0.1.255是公用组播地址可以用于Internet。
224.0.2.0238.255.255.255为用户可用的组播地址临时组地址全网范围内有效。
239.0.0.0239.255.255.255为本地管理组播地址仅在特定的本地范围内有效。
组播优势降低网络流量减轻硬件负荷减少冗余流量节约带宽。 组播应用多媒体、任何“单到多”数据发布应用。
2、单播、组播和广播的区别
组播(Multicast, 又称多播)是UDP专有的, 关于UDP的单播(Unicast), 组播, 广播(Broadcast)的区别, 网络上有张比较形象的图如下 组播工作原理
1组播使用特殊的IPv4组播地址224.0.0.0至239.255.255.255组播地址是一种特殊的IP地址用于标识一个组播组。
2Internet组管理协议IGMP是一种用于主机加入和离开组播组的协议。主机通过发送IGMP报文来通知路由器它们希望加入或离开一个组播组。路由器根据接收到的IGMP报文来维护组播组的成员列表。
3路由器组播数据的传输需要路由器的支持。路由器通过使用组播路由协议如PIM、IGMP等来维护组播组的成员信息并根据这些信息将组播数据转发到适当的接口上。
4数据传输当一个主机发送组播数据时它将数据包发送到一个特定的组播地址。路由器根据组播地址和组员列表来确定将数据包转发到哪些接口上。只有加入了组播组的主机才会接收到组播数据。
总结组播的原理是通过使用特定的组播地址和IGMP协议来实现多个主机之间的组播通信。路由器根据组员列表来转发组播数据只有加入了组播组的主机才能接收到数据。组播可以提供高效的数据传输适用于需要向多个目标主机发送相同数据的场景如视频流、实时通信等。
3、 加入和离开组播组
3.1指令方式
加入组播组指令sudo ip addr add 239.0.0.1 dev eth1 autojoin
离开组播组指令sudo ip addr del 239.0.0.1/24 dev eth1 autojoin
3.2代码方式
加入组播组加入组播组使用setsockopt设置IP_ADD_MEMBERSHIP选项。
struct ip_mreq multi_addr; bzero(multi_addr, sizeof(multi_addr)); multi_addr.imr_multiaddr.s_addr inet_addr(“239.0.0.1”); multi_addr.imr_interface.s_addr INADDR_ANY; setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)multi_addr, sizeof(multi_addr));
离开组播组离开组播组使用setsockopt设置IP_DROP_MEMBERSHIP选项。
struct ip_mreq multi_addr; bzero(multi_addr, sizeof(multi_addr)); multi_addr.imr_multiaddr.s_addr inet_addr(“239.0.0.1”); multi_addr.imr_interface.s_addr INADDR_ANY; setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void *)multi_addr, sizeof(multi_addr));
4、C语言编写接收和发送udp组播数据
4.1组播数据发送
//组播发送初始化
int initUdpMultiCastSender(uint32_t localip,uint16_t localport)
{int sockfd socket(AF_INET,SOCK_DGRAM,0);//创建套接字if (-1 sockfd){printf([initUdpMultiCastSender]socket fail\n);return -1;}//设置本地的组播地址和端口注意该port不是组播port而是本地portstruct sockaddr_in myaddr;memset(myaddr,0,sizeof(myaddr));myaddr.sin_family AF_INET;myaddr.sin_port htons(localport);myaddr.sin_addr.s_addr localip;int bindret bind(sockfd,(struct sockaddr *)(myaddr),sizeof(struct sockaddr));if (-1 bindret){perror([initUdpMultiCastSender]bind fail\n);close(sockfd);return -1;}return sockfd;
}
//组播数据发送--注意发送的ip和port为组播ip,port
int sendUdpMultiCast(int sockfd,char *pMultiCastIp,uint16_t multicastPort,void *data,uint32_t len)
{struct sockaddr_in destAddr;destAddr.sin_family AF_INET;destAddr.sin_addr.s_addr inet_addr(pMultiCastIp);destAddr.sin_port htons(multicastPort);int sendLen sendto(sockfd,data,len,0,(struct sockaddr *)(destAddr),sizeof(struct sockaddr));return sendLen;
}
4.2接收组播数据 int sockfd socket(AF_INET,SOCK_DGRAM,0);if (-1 sockfd){perror(socket fail\n);return -3;}printf(socket succ\n);struct ip_mreq mreq;memset(mreq,0,sizeof(struct ip_mreq));mreq.imr_interface.s_addr htonl(INADDR_ANY);mreq.imr_multiaddr.s_addr inet_addr(pUdpMultiCastIp);//加入组int setoptret setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,mreq,sizeof(struct ip_mreq));if (-1 setoptret){perror(setsockopt fail\n);return -4;}printf(setsockopt ip_add_membership succ\n);struct sockaddr_in peeraddr;memset(peeraddr,0,sizeof(struct sockaddr_in));peeraddr.sin_family AF_INET;peeraddr.sin_addr.s_addr inet_addr(pUdpMultiCastIp);peeraddr.sin_port htons(udpMultiCastPort);//绑定要接收的组播地址int bindRet bind(sockfd,(struct sockaddr *)(peeraddr),sizeof(struct sockaddr));if (-1 bindRet){perror(bind fail\n);return -5;}printf(bind succ\n);while(1){char buffer[1024] {0};socklen_t addrLen sizeof(struct sockaddr);printf(ready 2 recv\n);int recvRet recvfrom(sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)(peeraddr),addrLen);if (-1 recvRet){perror(recvfrom fail\n);break;}printf(recvfrom succ,buffer is %s\n,buffer);}
说明接收端的代码整体的思路就是创建socket-加入组播本地地址和组播地址赋值给mreq-绑定ip,port注意该ip和port是组播ip和组播port-接收数据注意接收的ip和port为组播ip,port。