On an Ubuntu 14.04 server I have two processes, each listening for multicast messages on the same port, but from different groups. I would not have expected this, but each sees traffic from both the group they want, and the other group.
As far as I can tell, this is known behavior (though I would call it a problem). I found this SO question, which provides some techniques for determining the multicast group that data is being received from, but it does not answer the question of why this is even happening in the first place. I would have thought that the underlying system network code would have filtered out messages on multicast groups I am not attempting to receive.
While I am mostly working in C++, I can provide some simple Python code to demonstrate the problem. In one terminal window I listen on multicast group 220.127.116.11, port 12345. In another terminal window on the same server I listen to multicast group 18.104.22.168, also port 12345. On a second machine, I transmit one multicast message on 22.214.171.124:12345, and a different message on 126.96.36.199:12345.
On svr3, the transmitter:
[email protected]:~$ mcast_snd 188.8.131.52 12345 "from 1.1.1" multicasting from 1.1.1 to 184.108.40.206 port 12345 [email protected]:~$ mcast_snd 220.127.116.11 12345 "from 2.2.2" multicasting from 2.2.2 to 18.104.22.168 port 12345
On svr2, window 1, the first receiver:
[email protected]:~$ mcast_rcv 22.214.171.124 12345 listening for multicast data on 126.96.36.199 port 12345 received 10 bytes: from 1.1.1 received 10 bytes: from 2.2.2
On svr2, terminal 2, the other receiver:
[email protected]:~$ mcast_rcv 188.8.131.52 12345 listening for multicast data on 184.108.40.206 port 12345 received 10 bytes: from 1.1.1 received 10 bytes: from 2.2.2
As you can see, both receivers receive both messages. Can someone explain why this is? And if there is a better way to configure the receivers to not receive messages from other groups, please share that too.
For reference, here is the code for mcast_rcv:
#!/usr/bin/python import socket import struct import sys if len(sys.argv) != 3: print 'usage:', sys.argv, '<multicast group>', '<multicast port>' sys.exit(0) mcast_group = sys.argv mcast_port = int(sys.argv) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(('', mcast_port)) mreq = struct.pack('4sl', socket.inet_aton(mcast_group), socket.INADDR_ANY) sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) print 'listening for multicast data on', mcast_group, 'port', mcast_port while True: msg = sock.recv(10240) print 'received', len(msg), 'bytes:', msg
And here is the code for mcast_snd:
#!/usr/bin/python import socket import sys if len(sys.argv) != 4: print 'usage:', sys.argv, '<multicast group>', '<multicast port>', '<mess age>' sys.exit(0) mcast_group = sys.argv mcast_port = int(sys.argv) message = sys.argv sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) print 'multicasting', message, 'to', mcast_group, 'port', mcast_port sock.sendto(message, (mcast_group, mcast_port))