Multicast
- netstat -g
- netstat -aun
- iptables -L
- iptables -F
All of them are handled via two system calls: setsockopt() (used to pass information to the kernel) and getsockopt() (to retrieve information regarded multicast behavior). socket of the family AF_INET type SOCK_DGRAM For multicast programming, level will always be IPPROTO_IP. optname identifies the option we are setting/getting. IP_ADD_MEMBERSHIP IP_MULTICAST_TTL IP_MULTICAST_IF IP_MULTICAST_TTL, multicast datagrams are sent with a default value of 1, to prevent them to be forwarded beyond the local network. IP_MULTICAST_IF, system administrator specifies the default interface multicast datagrams should be sent from. The programmer can override this and choose a concrete outgoing interface for a given socket with this option. In determining or selecting outgoing interfaces, the following ioctls might be useful: SIOCGIFADDR (to get an interface's address), SIOCGIFCONF (to get the list of all the interfaces) and SIOCGIFFLAGS (to get an interface's flags and, thus, determine whether the interface is multicast capable or not -the IFF_MULTICAST flag-). If the host has more than one interface and the IP_MULTICAST_IF option is not set, multicast transmissions are sent from the default interface tell the kernel which multicast groups you are interested in become a member of that group, you should first fill a ip_mreq imr_multiaddr, holds the group address you want to join. This way, if you are in a multihomed host, you can join the same group in several interfaces. You can always fill this last member with the wildcard address (INADDR_ANY) and then the kernel will deal with the task of choosing the interface. setsockopt (socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); MULTICAST Address | 224.0.0.0 - 239.255.255.255 the range 239.0.0.0 to 239.255.255.255 has been reserved for "administrative scoping" (see section 2.3.1 for information on administrative scoping). multicast traffic is handled at the transport layer with UDP In principle, an application just needs to open a UDP socket and fill with a class D multicast address the destination address where it wants to send data to. TTL thresholds 1 Restricted to the same subnet. Won't be forwarded by a router. When the sending host is Level 2 conformant and is also a member of the group datagrams are being sent to, a copy is looped back by default. Interface selection. Hosts attached to more than one network should provide a way for applications to decide which network interface will be used to output the transmissions. If not specified, the kernel chooses a default one based on system administrator's configuration. With multicast, however, it is necessary to advise the kernel which multicast groups we are interested in. That is, we have to ask the kernel to "join" those multicast groups. You join a group on a particular network interface. If you don't specify a concrete interface, then the kernel will choose it based on its routing tables when datagrams are to be sent. It is also possible that more than one process joins the same multicast group on the same interface. They will all receive the datagrams sent to that group via that interface.
C code publisher
publisher.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <arpa/inet.h>
8 #include <netinet/in.h>
9
10 #define PORT 4242
11 #define MAXLINE 1024
12
13 int main() {
14 int sockfd;
15 char *hello = "Hello from publisher!!!!!!!";
16 struct sockaddr_in servaddr;
17 sockfd = socket(AF_INET, SOCK_DGRAM, 0 );
18
19 memset(&servaddr, 0, sizeof(servaddr));
20 servaddr.sin_family = AF_INET;
21 servaddr.sin_port = htons(PORT);
22 servaddr.sin_addr.s_addr = inet_addr("225.3.2.1");
23
24 int n, len;
25 int size = strlen(hello)+1; // include null terminator
26 sendto(sockfd, (const char *)hello, size, MSG_CONFIRM, (const struct sockaddr *) &servaddr, sizeof(servaddr));
27 printf("Message %s sent.\n", hello);
28 close(sockfd);
29 return 0;
30 }
C code subscriber
subscriber.c
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <arpa/inet.h>
4 #include <netinet/in.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <string.h>
9
10 #define PORT 4242
11 #define MAXLINE 1024
12
13 int main() {
14 int sockfd;
15 char buffer[MAXLINE];
16 struct sockaddr_in servaddr, cliaddr;
17 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
18
19 memset(&servaddr, 0, sizeof(servaddr));
20 memset(&cliaddr, 0, sizeof(cliaddr));
21 servaddr.sin_family = AF_INET;
22 servaddr.sin_addr.s_addr = INADDR_ANY;
23 servaddr.sin_port = htons(PORT);
24
25 struct ip_mreq mreq;
26 mreq.imr_multiaddr.s_addr = inet_addr("225.3.2.1");
27 mreq.imr_interface.s_addr = INADDR_ANY;
28 int enable=1;
29 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int) );
30 setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int) );
31 setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq) );
32 bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr));
33
34 int len, bytes_received;
35 while(1){
36 bytes_received = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, ( struct sockaddr *) &cliaddr, &len);
37 printf("RX: %s\n", buffer);
38 }
39 return 0;
40 }
iptables
https://www.ibm.com/developerworks/community/blogs/fe313521-2e95-46f2-817d-44a4f27eba32/entry/configuring_iptables_for_ip_multicast1?lang=en Disabling iptables
If your multicast client system doesn't need to be protected by a firewall the easiest way to make a multicast application to work is by disabling iptables or any other firewall service that might be running. That can be done temporarily by flushing all the iptables rules with the following command:
# iptables -F
/etc/sysconfig/iptables By adding the following line to this file, iptables will allow all incoming multicast packets:
- -A INPUT -m pkttype --pkt-type multicast -j ACCEPT
python subscriber
subscriber.py
1 import socket
2
3 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
4
5 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
6 mreq = socket.inet_aton('225.3.2.1') + socket.inet_aton('0.0.0.0')
7 sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
8
9 sock.bind(('0.0.0.0', 4242))
10
11 while True:
12 print sock.recvfrom(1024)[0]
python publisher
publisher.py