Listing 1. Multicast Application
/* Blank lines have been deleted.
* If a numbered line does not fit the
* column width, it wraps.
*/
9 #include <stdio.h> /* printf(), snprintf() */
10 #include <stdlib.h> /* strtol(), exit() */
11 #include <sys/types.h>
12 #include <sys/socket.h> /* socket(),
setsockopt(), bind(), recvfrom(), sendto() */
13 #include <errno.h> /* perror() */
14 #include <netinet/in.h> /* IPPROTO_IP,
sockaddr_in, htons(), htonl() */
15 #include <arpa/inet.h> /* inet_addr() */
16 #include <unistd.h> /* fork(), sleep() */
17 #include <sys/utsname.h> /* uname() */
18 #include <string.h> /* memset() */
20 #define MAXLEN 1024
21 #define DELAY 2
22 #define TTL 1
25 int main(int argc, char* argv[])
26 {
27 u_char no = 0;
28 u_int yes = 1; /* Used with SO_REUSEADDR.
In Linux both u_int */
29 /* and u_char are valid. */
30 int send_s, recv_s; /* Sockets for sending
and receiving. */
31 u_char ttl;
32 struct sockaddr_in mcast_group;
33 struct ip_mreq mreq;
34 struct utsname name;
36 if ((argc<3) || (argc>4)) {
37 fprintf(stderr, "Usage: %s mcast_group
port [ttl]\n", argv[0]);
38 exit(1);
39 }
41 memset(&mcast_group, 0, sizeof(mcast_group));
42 mcast_group.sin_family = AF_INET;
43 mcast_group.sin_port = htons((unsigned short
int)strtol(argv[2], NULL, 0));
44 mcast_group.sin_addr.s_addr =
inet_addr(argv[1]);
46 if ( (send_s=socket(AF_INET, SOCK_DGRAM, 0))
< 0) {
47 perror ("send socket");
48 exit(1);
49 }
51 /* If ttl supplied, set it */
52 if (argc == 4) {
53 ttl = strtol(argv[3], NULL, 0);
54 } else {
55 ttl = TTL;
56 }
58 if (setsockopt(send_s, IPPROTO_IP,
IP_MULTICAST_TTL, &ttl,
59 sizeof(ttl)) < 0) {
60 perror ("ttl setsockopt");
61 exit(1);
62 }
64 /* Disable Loop-back */
65 if (setsockopt(send_s, IPPROTO_IP,
IP_MULTICAST_LOOP, &no,
66 sizeof(no)) < 0) {
67 perror ("loop setsockopt");
68 exit(1);
69 }
71 if ( (recv_s=socket(AF_INET, SOCK_DGRAM, 0))
< 0) {
72 perror ("recv socket");
73 exit(1);
74 }
76 if (setsockopt(recv_s, SOL_SOCKET,
SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
77 perror("reuseaddr setsockopt");
78 exit(1);
79 }
81 if (bind(recv_s, (struct
sockaddr*)&mcast_group,sizeof(mcast_group)) < 0){
82 perror ("bind");
83 exit(1);
84 }
86 /* Tell the kernel we want to join that
multicast group. */
87 mreq.imr_multiaddr = mcast_group.sin_addr;
88 mreq.imr_interface.s_addr = htonl(INADDR_ANY);
89 if (setsockopt(recv_s, IPPROTO_IP,
IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
90 perror ("add_membership setsockopt");
91 exit(1);
92 }
94 if (uname(&name) < 0) {
95 perror ("uname");
96 exit(1);
97 }
99 switch (fork()) {
100 case -1: /* Error fork()ing */
101 perror("fork");
102 exit(1);
103 case 0: { /* Child -> receive. */
104 int n;
105 int len;
106 struct sockaddr_in from;
107 char message [MAXLEN+1];
109 for (;;) {
110 len=sizeof(from);
111 if ( (n=recvfrom(recv_s, message,
MAXLEN, 0,
112 (struct sockaddr*)&from, &len))
< 0) {
113 perror ("recv");
114 exit(1);
115 }
116 message[n] = 0; /* null-terminate
string */
117 printf("%s: Received message from
%s.\n", name.nodename,
118 inet_ntoa(from.sin_addr));
119 printf("\t%s", message);
120 }
121 /* Not reached. */
122 }
123 default: { /* Parent -> send. */
124 char message [MAXLEN];
125 snprintf (message, sizeof(message),
"Hi, I'm %s. "
126 "Merry Christmas!\t(TTL==%d)\n",
name.nodename, ttl);
127 for (;;) {
128 if (sendto(send_s, message,
strlen(message), 0,
129 (struct sockaddr*)&mcast_group,
130 sizeof(mcast_group)) <
strlen(message)) {
131 perror("sendto");
132 exit(1);
133 }
134 sleep(DELAY);
135 }
136 /* Not reached. */
137 }
138 }
139 /* Not really reached. */
140 }
Copyright © 1994 - 2019 Linux Journal. All rights reserved.