为什么在同一个端口但是从不同的组合的多播消息?

在Ubuntu 14.04服务器上,我有两个进程,每个监听同一端口上的多播消息,但从不同的组中收听。 我不会期望这一点,但每个人都看到来自他们想要的团队和另一个团队的stream量。

据我所知,这是已知的行为(尽pipe我会把它称为一个问题)。 我发现了这个问题 ,它提供了一些技术来确定正在接收数据的多播组,但是它并没有回答为什么这个问题甚至发生在首位。 我原以为底层的系统networking代码会过滤掉我不想尝试接收的多播组消息。

虽然我主要使用C ++,但我可以提供一些简单的Python代码来演示这个问题。 在一个terminal窗口中,我侦听多播组239.1.1.1,端口12345.在同一服务器上的另一个terminal窗口中,侦听多播组239.2.2.2,也侦听端口12345.在第二台机器上,我在239.1上发送一个多播消息。 1.1:12345,在239.2.2.2:12345上有不同的消息。

在svr3上,发射器:

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 

在svr2窗口1,第一个接收器:

 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 

在svr2上,terminal2,另一个接收器:

 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 

正如你所看到的,两个接收器都接收这两个消息。 有人可以解释为什么这是? 如果有更好的方法来configuration接收器不接收来自其他组的消息,请分享。

作为参考,这里是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 

这里是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)) 

与在同一端口上接收多个多点传送馈送的主要区别- C,Linux是您正在使用python。

mcast_rcv您可以启用组过滤器禁用IP_MULTICAST_ALL选项,让INADDR_ANY如下所示:

 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) 

由于我使用的python没有定义socket.IP_MULTICAST_ALL ,可能需要定义它。

问题解决了。 我需要指定组播组绑定到接收者,而不仅仅是端口。 这个问题让我知道了。通过在Python代码中保留地址,或者在我的C ++中保留INADDR_ANY ,我基本上告诉操作系统,我希望在那个端口上的所有消息,不管是哪个组。 系统正在给我我正在要求的东西,就像它总是这样。

如果我用sock.bind((mcast_group, mcast_port))替换sock.bind(('', mcast_port))行,行为就像我期望的那样。 仅仅加入多播组( sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) )是不足以过滤掉该端口上的非组消息的。