Why are multicast messages on the same port but from different groups combined? [duplicate]

半腔热情 提交于 2019-12-23 01:40:07

问题


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 239.1.1.1, port 12345. In another terminal window on the same server I listen to multicast group 239.2.2.2, also port 12345. On a second machine, I transmit one multicast message on 239.1.1.1:12345, and a different message on 239.2.2.2:12345.

On svr3, the transmitter:

rcook@svr3:~$ mcast_snd 239.1.1.1 12345 "from 1.1.1"
multicasting from 1.1.1 to 239.1.1.1 port 12345
rcook@svr3:~$ mcast_snd 239.2.2.2 12345 "from 2.2.2"
multicasting from 2.2.2 to 239.2.2.2 port 12345

On svr2, window 1, the first receiver:

rcook@svr2:~$ mcast_rcv 239.1.1.1 12345
listening for multicast data on 239.1.1.1 port 12345
received 10 bytes: from 1.1.1
received 10 bytes: from 2.2.2

On svr2, terminal 2, the other receiver:

rcook@svr2:~$ mcast_rcv 239.2.2.2 12345
listening for multicast data on 239.2.2.2 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[0], '<multicast group>', '<multicast port>'
    sys.exit(0)

mcast_group = sys.argv[1]
mcast_port = int(sys.argv[2])

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[0], '<multicast group>', '<multicast port>', '<mess
age>'
    sys.exit(0)

mcast_group = sys.argv[1]
mcast_port = int(sys.argv[2])
message = sys.argv[3]

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))

回答1:


The main difference with the Receving multiple multicast feeds on the same port - C, Linux is you are using python.

In mcast_rcv you can enable the group filter disabling the IP_MULTICAST_ALL option, letting the INADDR_ANY like this :

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)
# disable mc_all 
if hasattr(socket,'IP_MULTICAST_ALL') != True:
    socket.IP_MULTICAST_ALL = 49
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_ALL, 0)

As the python I used doesnot define socket.IP_MULTICAST_ALL, it could be needed to define it.




回答2:


Problem solved. I need to specify the multicast group to bind to in the receiver, not just the port. This SO question clued me in. By leaving the address as '' in the Python code, or INADDR_ANY in my C++, I am basically telling the OS that I want all messages on that port, regardless of group. The system is giving me exactly what I am asking for, like it always does.

If I replace the line sock.bind(('', mcast_port)) with sock.bind((mcast_group, mcast_port)) in mcast_rcv, the behavior is as I expect and want. Merely joining the multicast group (sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)) is not enough to filter out non-group messages on that port.



来源:https://stackoverflow.com/questions/29833542/why-are-multicast-messages-on-the-same-port-but-from-different-groups-combined

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!