Penguin
Blame: SourceSpecificMulticastExample
EditPageHistoryDiffInfoLikePages
Annotated edit history of SourceSpecificMulticastExample version 6, including all changes. View license author blame.
Rev Author # Line
4 PerryLorier 1 Here are some trivial examples of working [SSM] code. They certainly work under [LinuxKernel2.6], and have been tested on [amd64] in [Gentoo] and on [ia32] DebianLinux. It's possible that [SSM] is not supported in [Linux] 2.4. The examples join the [SSM] group ''ip-of-sender, 232.1.1.1''. In a real application you should randomly select the 232.0.0.0/8 address at runtime to avoid conflicts.
1 AristotlePagaltzis 2
3 Note that some information is included in <tt>#ifndef</tt>s since many LinuxDistribution~s don't install the required header files yet.
4
5 I had one major problem while trying to debug this. My mistake was that the reciever wasn't binding to <tt>INADDR_ANY</tt> for the listening socket, but instead to an [IP] address on the machine. This caused all the multicast packets to be ignored. Oops.
5 PerryLorier 6
7 Another bug was due to the server using the SSM source of the unassigned address. Oops.
1 AristotlePagaltzis 8
9 Sender::
10
11 <verbatim>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <arpa/inet.h>
15 #include <netinet/in.h>
16 #include <netdb.h>
17 #include <string.h>
18 #include <unistd.h>
19
20 /* Not everyone has the headers for this so improvise */
21 #ifndef MCAST_JOIN_SOURCE_GROUP
22 #define MCAST_JOIN_SOURCE_GROUP 46
23
24 struct group_source_req
25 {
26 /* Interface index. */
27 uint32_t gsr_interface;
28
29 /* Group address. */
30 struct sockaddr_storage gsr_group;
31
32 /* Source address. */
33 struct sockaddr_storage gsr_source;
34 };
35 #endif
36
37 int main(int argc, char *argv[])
38 {
39 struct group_source_req group_source_req;
40 struct sockaddr_in *group;
41 struct sockaddr_in *source;
42 int fd = socket(AF_INET,SOCK_DGRAM,getprotobyname("udp")->p_proto);
43 socklen_t socklen = sizeof(struct sockaddr_storage);
44 struct sockaddr_in bindaddr;
45 u_char loop = 1;
46
47 /* First bind to the port */
48 bindaddr.sin_family = AF_INET;
49 bindaddr.sin_port = htons(9990);
50 bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
51
52 bind(fd,(struct sockaddr*)&bindaddr,sizeof(bindaddr));
53 /* Now set up the SSM request */
54 group_source_req.gsr_interface = 0; /* "any" interface */
55 group=(struct sockaddr_in*)&group_source_req.gsr_group;
56 source=(struct sockaddr_in*)&group_source_req.gsr_source;
57
58 group->sin_family = AF_INET;
59 inet_aton("232.1.1.1",&group->sin_addr);
60 group->sin_port = 0; /* Ignored */
61
62 /* Set the source to the name of the socket we created above */
63 getsockname(fd,(struct sockaddr *)source, &socklen);
64
65 setsockopt(fd,SOL_IP,MCAST_JOIN_SOURCE_GROUP, &group_source_req,
66 sizeof(group_source_req));
67
68 /* Enable reception of our own multicast */
69 loop = 1;
70 setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
71 /* Set the TTL on packets to 250 */
72 loop=250;
73 setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &loop, sizeof(loop));
74 /* Now we care about the port we send to */
75 group->sin_port = htons(9991);
76
77 /* Now send packets */
78 while(1) {
79 sendto(fd,"Hello World",strlen("Hello World"),0,
80 (struct sockaddr*)group,sizeof(struct sockaddr_in));
81 sleep(1);
82 }
83 return 0;
84 }
85 </verbatim>
86
6 PaulWankadia 87 Receiver::
1 AristotlePagaltzis 88
89 Pass the [IP] address of the sender as CommandLine argument: <tt>./ssm-rec ip.address.of.sender</tt>
90
91 <verbatim>
92 #include <sys/types.h>
93 #include <sys/socket.h>
94 #include <arpa/inet.h>
95 #include <netinet/in.h>
96 #include <netdb.h>
97 #include <unistd.h>
98
99 /* Not everyone has the headers for this, so improvise */
100 #ifndef MCAST_JOIN_SOURCE_GROUP
101 #define MCAST_JOIN_SOURCE_GROUP 46
102
103 struct group_source_req
104 {
105 /* Interface index. */
106 uint32_t gsr_interface;
107
108 /* Group address. */
109 struct sockaddr_storage gsr_group;
110
111 /* Source address. */
112 struct sockaddr_storage gsr_source;
113 };
114 #endif
115
116 int main(int argc, char *argv[])
117 {
118 struct group_source_req group_source_req;
119 struct sockaddr_in *group;
120 struct sockaddr_in *source;
121 int fd = socket(AF_INET,SOCK_DGRAM,getprotobyname("udp")->p_proto);
122 struct sockaddr_in bindaddr;
123
124 /* Setup the socket to listen on */
125 bindaddr.sin_family = AF_INET;
126 bindaddr.sin_port = htons(9991);
127 bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
128 bind(fd,(struct sockaddr*)&bindaddr,sizeof(bindaddr));
129
130 /* Set up the connection to the group */
131 group_source_req.gsr_interface = 0;
132 group=(struct sockaddr_in*)&group_source_req.gsr_group;
133 source=(struct sockaddr_in*)&group_source_req.gsr_source;
134 /* Group is 232.1.1.1 */
135 group->sin_family = AF_INET;
136 inet_aton("232.1.1.1",&group->sin_addr);
137 group->sin_port = 0;
138
139 /* Source is 10.1.20.9 */
140 source->sin_family = AF_INET;
141 inet_aton(argv[1],&source->sin_addr);
142 source->sin_port = 0;
143
144 setsockopt(fd,SOL_IP,MCAST_JOIN_SOURCE_GROUP, &group_source_req,
145 sizeof(group_source_req));
146
147 while(1) {
148 char buffer[65536];
149 int ret=recv(fd,(char*)buffer,sizeof(buffer),0);
150 write(1,buffer,ret);
151 }
152 return 0;
153 }
6 PaulWankadia 154 </verbatim>
155
156 Python::
157
158 <verbatim>
159 #! /usr/bin/python
160
161 import getopt
162 import socket
163 import sys
164
165 if not hasattr(socket, 'IP_MULTICAST_TTL'):
166 setattr(socket, 'IP_MULTICAST_TTL', 33)
167 if not hasattr(socket, 'IP_ADD_SOURCE_MEMBERSHIP'):
168 setattr(socket, 'IP_ADD_SOURCE_MEMBERSHIP', 39)
169
170 if sys.argv[1] == 'send':
171 opts, args = getopt.getopt(sys.argv[2:], 't:s:g:p:')
172 opts = dict(opts)
173
174 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
175 if '-t' in opts:
176 s.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, chr(int(opts['-t'])))
177 if '-s' in opts:
178 s.bind((opts['-s'], 0))
179 s.connect((opts['-g'], int(opts['-p'])))
180 print 'READY.'
181 while True:
182 s.send(sys.stdin.readline())
183
184 elif sys.argv[1] == 'recv':
185 opts, args = getopt.getopt(sys.argv[2:], 'g:i:s:p:')
186 opts = dict(opts)
187 opts.setdefault('-i', '0.0.0.0')
188
189 imr = (socket.inet_pton(socket.AF_INET, opts['-g']) +
190 socket.inet_pton(socket.AF_INET, opts['-i']) +
191 socket.inet_pton(socket.AF_INET, opts['-s']))
192
193 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
194 s.setsockopt(socket.SOL_IP, socket.IP_ADD_SOURCE_MEMBERSHIP, imr)
195 s.bind((opts['-g'], int(opts['-p'])))
196 print 'READY.'
197 while True:
198 print repr(s.recvfrom(4096))
1 AristotlePagaltzis 199 </verbatim>
200
201 ----
202 Part of CategoryProgramming and CategoryNetworking