组播

组播

单播只能发给一个接收方,广播发给所有主机,但过多的广播会大量占用网络带宽,造成网络风暴,影响通信。

组播(多播)为折中方式,只有加入某个多播组的主机才能收到数据。

组播的IP地址:224.0.0.1 ~ 239.255.255.254(中间除去广播地址)


组播的发送

1)创建UDP套接字

2)指定目标地址与端口

3)发送数据包

 1 /*udp demo */
 2 
 3 /* usage:
 4  * ./client serv_ip serv_port 
 5 */
 6 #include "net.h"
 7 void usage (char *s)
 8 {
 9     printf ("\nThis is multicast demo!\n");
10     printf ("\nUsage:\n\t %s serv_ip serv_port", s);
11     printf ("\n\t serv_ip: udp server ip address(between 224~239 segment)");
12     printf ("\n\t serv_port: udp server port(serv_port > 5000)\n\n");
13 }
14 
15 int main (int argc, char *argv[])
16 {
17     int fd = -1;
18     int port = SERV_PORT;
19 
20     port = atoi (argv[2]);
21     if (port < 0 || (port > 0 && port <= 5000)) {
22         usage (argv[0]);
23         exit (1);
24     }
25     struct sockaddr_in sin;
26     if (argc != 3) {
27         usage (argv[0]);
28         exit (1);
29     }
30 
31     /* 1. 创建socket fd */
32     if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {    //UDP缂栫▼
33         perror ("socket");
34         exit (1);
35     }
36 
37     /*2.1 填充struct sockaddr_in */
38     bzero (&sin, sizeof (sin));
39 
40     sin.sin_family = AF_INET;
41     sin.sin_port = htons (SERV_PORT);    //HBD转为NBD
42 #if 0
43     sin.sin_addr.s_addr = inet_addr (argv[1]);
44 #else
45     if (inet_pton (AF_INET, argv[1], (void *) &sin.sin_addr) != 1) {
46         perror ("inet_pton");
47         exit (1);
48     }
49 #endif
50     printf ("multicast started!\n");
51     char buf[BUFSIZ];
52     while (1) {
53         fprintf (stderr, "pls input string:");
54         bzero (buf, BUFSIZ);
55         if (fgets (buf, BUFSIZ - 1, stdin) == NULL) {
56             perror ("fgets");
57             continue;
58         }
59 
60         sendto (fd, buf, strlen (buf), 0, (struct sockaddr *) &sin, sizeof (sin));
61 
62         if (!strncasecmp (buf, QUIT_STR, strlen (QUIT_STR))) {    
63             printf ("Client is exited!\n");
64             break;
65         }
66 
67     }
68     close (fd);
69     return 0;
70 }
sender.c

组播的接收

1)创建UDP套接字

2)加入多播组

3)绑定地址与端口

4)接收数据包

 1 #include "net.h"
 2 
 3 int main (void)
 4 {
 5 
 6     int fd = -1;
 7     struct sockaddr_in sin;
 8 
 9     /* 1. 创建socket fd */
10     if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {    //udp
11         perror ("socket");
12         exit (1);
13     }
14 
15     /* 2. 允许地址快速重用 */
16     int b_reuse = 1;
17     setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof (int));
18 
19     /*加入多播组*/
20     struct ip_mreq mreq;
21     bzero(&mreq, sizeof(mreq)); //清零
22     mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_IP);
23     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
24     
25     setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq, sizeof(mreq));
26 
27     /*2. 绑定*/
28     /*2.1 填充struct sockaddr_in */
29     bzero (&sin, sizeof (sin));
30     sin.sin_family = AF_INET;
31     sin.sin_port = htons (SERV_PORT);    
32     /* 使服务器可绑定在任意IP */
33 #if 1
34     sin.sin_addr.s_addr = htonl (INADDR_ANY);
35 #else
36     if (inet_pton (AF_INET, SERV_IP_ADDR, (void *) &sin.sin_addr) != 1) {
37         perror ("inet_pton");
38         exit (1);
39     }
40 #endif
41     /*2.2 绑定 */
42     if (bind (fd, (struct sockaddr *) &sin, sizeof (sin)) < 0) {
43         perror ("bind");
44         exit (1);
45     }
46 
47     char buf[BUFSIZ];
48     struct sockaddr_in cin;
49     socklen_t addrlen = sizeof (cin);
50     printf ("\nmulticast demo started!\n");
51     while (1) {
52         bzero (buf, BUFSIZ);
53         if (recvfrom (fd, buf, BUFSIZ - 1, 0, (struct sockaddr *) &cin, &addrlen) < 0) {
54             perror ("recvfrom");
55             continue;
56         }
57 
58         char ipv4_addr[16];
59         if (!inet_ntop (AF_INET, (void *) &cin.sin_addr, ipv4_addr, sizeof (cin))) {
60             perror ("inet_ntop");
61             exit (1);
62         }
63 
64         printf ("Recived from(%s:%d), data:%s", ipv4_addr, ntohs (cin.sin_port), buf);
65 
66         if (!strncasecmp (buf, QUIT_STR, strlen (QUIT_STR))) {    /
67             printf ("Client(%s:%d) is exiting!\n", ipv4_addr, ntohs (cin.sin_port));
68         }
69 
70     }
71 
72     close (fd);
73 
74     return 0;
75 }
recever.c

 

posted @ 2020-01-29 00:10  朱果果  阅读(580)  评论(0编辑  收藏  举报