version 6, including all changes.
.
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 |