Home
Main website
Display Sidebar
Hide Ads
Recent Changes
View Source:
SourceSpecificMulticastExample
Edit
PageHistory
Diff
Info
LikePages
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. Note that some information is included in <tt>#ifndef</tt>s since many LinuxDistribution~s don't install the required header files yet. 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. Another bug was due to the server using the SSM source of the unassigned address. Oops. Sender:: <verbatim> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netdb.h> #include <string.h> #include <unistd.h> /* Not everyone has the headers for this so improvise */ #ifndef MCAST_JOIN_SOURCE_GROUP #define MCAST_JOIN_SOURCE_GROUP 46 struct group_source_req { /* Interface index. */ uint32_t gsr_interface; /* Group address. */ struct sockaddr_storage gsr_group; /* Source address. */ struct sockaddr_storage gsr_source; }; #endif int main(int argc, char *argv[]) { struct group_source_req group_source_req; struct sockaddr_in *group; struct sockaddr_in *source; int fd = socket(AF_INET,SOCK_DGRAM,getprotobyname("udp")->p_proto); socklen_t socklen = sizeof(struct sockaddr_storage); struct sockaddr_in bindaddr; u_char loop = 1; /* First bind to the port */ bindaddr.sin_family = AF_INET; bindaddr.sin_port = htons(9990); bindaddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(fd,(struct sockaddr*)&bindaddr,sizeof(bindaddr)); /* Now set up the SSM request */ group_source_req.gsr_interface = 0; /* "any" interface */ group=(struct sockaddr_in*)&group_source_req.gsr_group; source=(struct sockaddr_in*)&group_source_req.gsr_source; group->sin_family = AF_INET; inet_aton("232.1.1.1",&group->sin_addr); group->sin_port = 0; /* Ignored */ /* Set the source to the name of the socket we created above */ getsockname(fd,(struct sockaddr *)source, &socklen); setsockopt(fd,SOL_IP,MCAST_JOIN_SOURCE_GROUP, &group_source_req, sizeof(group_source_req)); /* Enable reception of our own multicast */ loop = 1; setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)); /* Set the TTL on packets to 250 */ loop=250; setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &loop, sizeof(loop)); /* Now we care about the port we send to */ group->sin_port = htons(9991); /* Now send packets */ while(1) { sendto(fd,"Hello World",strlen("Hello World"),0, (struct sockaddr*)group,sizeof(struct sockaddr_in)); sleep(1); } return 0; } </verbatim> Receiver:: Pass the [IP] address of the sender as CommandLine argument: <tt>./ssm-rec ip.address.of.sender</tt> <verbatim> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netdb.h> #include <unistd.h> /* Not everyone has the headers for this, so improvise */ #ifndef MCAST_JOIN_SOURCE_GROUP #define MCAST_JOIN_SOURCE_GROUP 46 struct group_source_req { /* Interface index. */ uint32_t gsr_interface; /* Group address. */ struct sockaddr_storage gsr_group; /* Source address. */ struct sockaddr_storage gsr_source; }; #endif int main(int argc, char *argv[]) { struct group_source_req group_source_req; struct sockaddr_in *group; struct sockaddr_in *source; int fd = socket(AF_INET,SOCK_DGRAM,getprotobyname("udp")->p_proto); struct sockaddr_in bindaddr; /* Setup the socket to listen on */ bindaddr.sin_family = AF_INET; bindaddr.sin_port = htons(9991); bindaddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(fd,(struct sockaddr*)&bindaddr,sizeof(bindaddr)); /* Set up the connection to the group */ group_source_req.gsr_interface = 0; group=(struct sockaddr_in*)&group_source_req.gsr_group; source=(struct sockaddr_in*)&group_source_req.gsr_source; /* Group is 232.1.1.1 */ group->sin_family = AF_INET; inet_aton("232.1.1.1",&group->sin_addr); group->sin_port = 0; /* Source is 10.1.20.9 */ source->sin_family = AF_INET; inet_aton(argv[1],&source->sin_addr); source->sin_port = 0; setsockopt(fd,SOL_IP,MCAST_JOIN_SOURCE_GROUP, &group_source_req, sizeof(group_source_req)); while(1) { char buffer[65536]; int ret=recv(fd,(char*)buffer,sizeof(buffer),0); write(1,buffer,ret); } return 0; } </verbatim> Python:: <verbatim> #! /usr/bin/python import getopt import socket import sys if not hasattr(socket, 'IP_MULTICAST_TTL'): setattr(socket, 'IP_MULTICAST_TTL', 33) if not hasattr(socket, 'IP_ADD_SOURCE_MEMBERSHIP'): setattr(socket, 'IP_ADD_SOURCE_MEMBERSHIP', 39) if sys.argv[1] == 'send': opts, args = getopt.getopt(sys.argv[2:], 't:s:g:p:') opts = dict(opts) s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) if '-t' in opts: s.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, chr(int(opts['-t']))) if '-s' in opts: s.bind((opts['-s'], 0)) s.connect((opts['-g'], int(opts['-p']))) print 'READY.' while True: s.send(sys.stdin.readline()) elif sys.argv[1] == 'recv': opts, args = getopt.getopt(sys.argv[2:], 'g:i:s:p:') opts = dict(opts) opts.setdefault('-i', '0.0.0.0') imr = (socket.inet_pton(socket.AF_INET, opts['-g']) + socket.inet_pton(socket.AF_INET, opts['-i']) + socket.inet_pton(socket.AF_INET, opts['-s'])) s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) s.setsockopt(socket.SOL_IP, socket.IP_ADD_SOURCE_MEMBERSHIP, imr) s.bind((opts['-g'], int(opts['-p']))) print 'READY.' while True: print repr(s.recvfrom(4096)) </verbatim> ---- Part of CategoryProgramming and CategoryNetworking
One page links to
SourceSpecificMulticastExample
:
SourceSpecificMulticast