组播的介绍以及CS模型实现
1.组播介绍
组播组可以是永久的也可以是临时的。组播组地址中,有一部分由官方分配的,称为永久组播组。
永久组播组保持不变的是它的ip地址,组中的成员构成可以发生变化。永久组播组中成员的数量都可以是任意的,甚至可以为零。
那些没有保留下来供永久组播组使用的ip组播地址,可以被临时组播组利用。
224.0.0.0~224.0.0.255 为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;
224.0.1.0~224.0.1.255 是公用组播地址,可以用于Internet;欲使用需申请。
224.0.2.0~238.255.255.255 为用户可用的组播地址(临时组地址),全网范围内有效;
239.0.0.0~239.255.255.255 为本地管理组播地址,仅在特定的本地范围内有效。
可使用ip ad命令查看网卡编号或者if_nametoindex() 函数可以根据网卡名,获取网卡序号。
2.代码实现
server.c
1 #include<stdio.h> 2 #include<unistd.h> 3 #include<stdlib.h> 4 #include<strings.h> 5 #include<string.h> 6 #include<sys/socket.h> 7 #include<arpa/inet.h> 8 #include<net/if.h> 9 10 #define SERVER_PORT 8000 11 #define MAXLINE 1024 12 #define CLIENT_PORT 9000 13 14 #define GROUP "239.0.0.2" 15 16 int main(int argc,char* argv[]) 17 { 18 int sockfd; 19 struct sockaddr_in servaddr,clieaddr; 20 char buf[MAXLINE]; 21 struct ip_mreqn group; 22 //构造用于UDP通信的套接字 23 sockfd = socket(AF_INET,SOCK_DGRAM,0); 24 25 bzero(&servaddr,sizeof(servaddr)); 26 servaddr.sin_family = AF_INET; 27 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 28 servaddr.sin_port = htons(SERVER_PORT); 29 30 bind(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)); 31 32 inet_pton(AF_INET,GROUP,&group.imr_multiaddr);//设置组地址 33 inet_pton(AF_INET,"0.0.0.0",&group.imr_address);//本地有效IP 34 group.imr_ifindex = if_nametoindex("eth0");//给出网卡名,转换为对应编号 35 36 setsockopt(sockfd,IPPROTO_IP,IP_MULTICAST_IF,&group,sizeof(group));//组播的权限设置 37 38 bzero(&clieaddr,sizeof(clieaddr)); 39 clieaddr.sin_family = AF_INET; 40 inet_pton(AF_INET,GROUP,&clieaddr.sin_addr.s_addr); 41 clieaddr.sin_port = htons(CLIENT_PORT); 42 43 int i = 1; 44 while(1) 45 { 46 sprintf(buf,"服务端组播了 %d次\n",i++); 47 sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&clieaddr,sizeof(clieaddr)); 48 sleep(1); 49 } 50 close(sockfd); 51 return 0; 52 }
client.c
1 #include<stdio.h> 2 #include<unistd.h> 3 #include<stdlib.h> 4 #include<strings.h> 5 #include<string.h> 6 #include<sys/socket.h> 7 #include<arpa/inet.h> 8 #include<net/if.h> 9 10 #define SERVER_PORT 8000 11 #define CLIENT_PORT 9000 12 13 #define GROUP "239.0.0.2" 14 15 int main(int argc,char* argv[]) 16 { 17 struct sockaddr_in localaddr; 18 int confd; 19 ssize_t len; 20 char buf[BUFSIZ]; 21 22 struct ip_mreqn group; 23 24 confd = socket(AF_INET,SOCK_DGRAM,0); 25 26 bzero(&localaddr,sizeof(localaddr)); 27 localaddr.sin_family = AF_INET; 28 inet_pton(AF_INET,"0.0.0.0",&localaddr.sin_addr.s_addr); 29 localaddr.sin_port = htons(CLIENT_PORT); 30 31 bind(confd,(struct sockaddr*)&localaddr,sizeof(localaddr)); 32 33 inet_pton(AF_INET,GROUP,&group.imr_multiaddr); 34 inet_pton(AF_INET,"0.0.0.0",&group.imr_address); 35 group.imr_ifindex = if_nametoindex("eth0"); 36 37 setsockopt(confd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&group,sizeof(group)); 38 39 while(1) 40 { 41 len = recvfrom(confd,buf,sizeof(buf),0,NULL,0); 42 write(STDOUT_FILENO,buf,len); 43 } 44 close(confd); 45 return 0; 46 }
3.测试结果
可以看到服务端启动后,客户端可以接收到服务端发送的组播信息
努力不一定有结果,有结果不一定是努力