Linux 网络通信之组播

组播可以看成是单播和广播的折中。当发送组播数据包时,只有加入指定多播组的主机数据链路层才会处理,其他主机在数据链路层会直接丢掉收到的数据包。即我们可以通过组播的方式和指定的若干台主机通信。

D类地址:范围从224.0.0.1到239.255.255.254.此类地址又称为组播地址。每个组播地址代表一个多播组。

组播包的发送和接收通过UDP套接字实现。

组播包发送流程如下:

(1)创建UDP套接字;socket(AF_INET, SOCK_DGRAM, 0)

(2)指定目标地址和端口;struct sockaddr_in

(3)发送数据包;sendto( )

send.c

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <sys/types.h>
 5 #include <sys/socket.h>
 6 #include <arpa/inet.h>
 7 #include <netinet/in.h>
 8 #include <string.h>
 9 
10 #define  err_log(log) do{perror(log); exit(1);}while(0)
11 
12 #define  N 128
13 
14 int main(int argc, const char *argv[])
15 {
16     
17     int sockfd;
18     struct sockaddr_in groupcastaddr;
19     char buf[N] = {0};
20 
21     if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
22     {
23         err_log("fail to socket");
24     }
25 
26     groupcastaddr.sin_family = AF_INET;
27     groupcastaddr.sin_addr.s_addr = inet_addr("225.0.0.3");
28     groupcastaddr.sin_port = htons(10000);
29 
30     while(1)
31     {
32         printf("Input > ");
33         fgets(buf, N, stdin);
34         if(sendto(sockfd,buf, N, 0, (struct sockaddr *)&groupcastaddr, sizeof(groupcastaddr)) < 0)
35         {
36             err_log("fail to sendto");
37         }
38         
39     }
40 
41     return 0;
42 }

组播接收流程如下:

(1)创建UDP套接字;socket(AF_INET, SOCK_DGRAM, 0)

(2)加入多播组;setsockopt( )

(3)填充组播地址信息(组播IP地址和端口);struct sockaddr_in

(4)接收数据包;recvfrom( )

多播结构体:

 1 struct ip_mreq                                                                                                    
 2 {
 3       /* IP multicast address of group.  */  组播的ip地址
 4       struct in_addr imr_multiaddr;
 5   
 6       /* Local IP address of interface.   */  本机的ip地址 
 7       struct in_addr imr_interface;
 8 };
 9 
10 mreq.imr_multiaddr.s_addr = inet_addr(“224.10.10.1”);  //组播地址
11 mreq.imr_interface.s_addr = htonl(INADDR_ANY);  //INADDR_ANY  0 地址 ,任意的主机地址
12 
13 setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

recv.c

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <sys/types.h>
 5 #include <sys/socket.h>
 6 #include <arpa/inet.h>
 7 #include <netinet/in.h>
 8 #include <string.h>
 9 
10 #define  err_log(log) do{perror(log); exit(1);}while(0)
11 #define  N  128
12 
13 int main(int argc, const char *argv[])
14 {
15     
16     int sockfd;
17     char buf[N];
18     struct sockaddr_in groupcastaddr, srcaddr;
19     struct ip_mreq mreq;
20 
21     if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
22     {
23         err_log("fail to socket");
24     }
25     /*为套接字绑定组播地址和端口*/
26     groupcastaddr.sin_family = AF_INET;
27     groupcastaddr.sin_addr.s_addr = inet_addr("225.0.0.3");
28     groupcastaddr.sin_port = htons(10000);
29 
30     /*加入多播组,允许数据链路层处理指定组播包*/
31     mreq.imr_multiaddr.s_addr = inet_addr("225.0.0.3");
32     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
33 
34     if(setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq, sizeof(mreq)) < 0)
35     {
36         err_log("fail to setsockopt");
37     }
38 
39     int on = 1;
40     if(setsockopt(sockfd,SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
41     {
42         err_log("fail to setsockopt");
43     }
44 
45     if(bind(sockfd, (struct sockaddr*)&groupcastaddr, sizeof(groupcastaddr)) < 0)
46     {
47         err_log("fail to bind");
48     }
49 
50     socklen_t addrlen = sizeof(struct sockaddr);
51 
52     while(1)
53     {
54         if(recvfrom(sockfd,buf, N, 0, (struct sockaddr *)&srcaddr, &addrlen) < 0)
55         {
56             err_log("fail to sendto");
57         }
58         printf("buf:%s ---> %s %d
", buf, inet_ntoa(srcaddr.sin_addr), ntohs(srcaddr.sin_port));
59     }
60 
61     return 0;
62 }
原文地址:https://www.cnblogs.com/yangziwen0709/p/5026028.html