组播
单播只能发给一个接收方,广播发给所有主机,但过多的广播会大量占用网络带宽,造成网络风暴,影响通信。
组播(多播)为折中方式,只有加入某个多播组的主机才能收到数据。
组播的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 }
组播的接收
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 }
来源:https://www.cnblogs.com/y4247464/p/12239414.html
