0

我正在尝试扭曲 python 的多播协议。这是一个简单的例子:

我创建了两个服务器,监听 224.0.0.1 和 224.0.0.2,如下所示:

from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
from twisted.application.internet import MulticastServer

class MulticastServerUDP(DatagramProtocol):
    def __init__ (self, group, name):
        self.group = group
        self.name = name
    def startProtocol(self):
        print '%s Started Listening' % self.group
        # Join a specific multicast group, which is the IP we will respond to
        self.transport.joinGroup(self.group)

    def datagramReceived(self, datagram, address):
        print "%s Received:"%self.name + repr(datagram) + repr(address)


reactor.listenMulticast(10222, MulticastServerUDP('224.0.0.1', 'SERVER1'), listenMultiple = True)
reactor.listenMulticast(10222, MulticastServerUDP('224.0.0.1', 'SERVER2'), listenMultiple = True)

reactor.run()

然后我运行这段代码发送“HELLO”:

import socket

MCAST_GRP = '224.0.0.1'
MCAST_PORT = 10222

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
sock.sendto("HELLO", (MCAST_GRP, MCAST_PORT))

结果相当混乱。有几种情况:

- 当我将所有组 IP 和 MCAST_GRP 设置为 224.0.0.1 时,两台服务器都收到了消息(预期) - 当我在发送脚本中将两台服务器的组 IP 设置为 224.0.0.1 和 MCAST_GRP 为 224.0.0.2(或不同于224.0.0.1),两台服务器都没有收到消息(预期)

- 当我将一台服务器的组 IP 设置为 224.0.0.1 和其他 224.0.0.2 时,发生了奇怪的事情。当我将 MCAST_GRP 设置为 224.0.0.1 或 224.0.0.2 时,我希望两台服务器中只有一台能够接收到消息。结果是两个服务器都收到了消息。我不确定发生了什么。有人可以解释一下吗?

注意:我在同一台机器上运行这些。

SL

4

2 回答 2

2

确实,这有点棘手。你必须这样写:

reactor.listenMulticast(
    10222, 
    MulticastServerUDP('224.0.0.1', 'SERVER1'),
    listenMultiple=True,
    interface='224.0.0.1'
)

reactor.listenMulticast(
    10222, 
    MulticastServerUDP('224.0.0.2', 'SERVER2'),
    listenMultiple=True,
    interface='224.0.0.2'
)

我以前也有同样的问题。我不得不查看源代码才能找到它。但我解决了这个问题,因为我有 C 网络编程的背景。

于 2012-07-31T09:52:24.860 回答
1

多播是古怪的,多播的平台(Linux、Windows、OS X 等)实现甚至更加古怪。

Twisted 在这里只是反映了平台的多播行为,所以这只是一个模糊的与 Twisted 相关的问题。实际上,这是一个多播问题和一个平台问题。

这是关于发生了什么的稍微有根据的猜测。

多播通过让主机订阅地址来工作。当主机上运行的程序加入一个组(例如 224.0.0.1)时,主机会在本地记录这一点并执行一些网络操作(IGMP)来告诉附近的主机(可能通过路由器,但我对这部分的详细信息)它现在对该组的消息感兴趣。

在多播创建者的理想世界中,订阅一直通过互联网传播。这是必要的,以便互联网上任何地方的任何人向该组发送消息时,无论哪个路由器得到消息,都可以将其传递给已订阅该组的所有主机。这应该比广播更有效,因为只有订阅的主机需要将消息传递给他们。由于路由器正在跟踪订阅,因此它们可以跳过向没有订阅主机的链路发送流量。

在现实世界中,多播订阅通常不会传播很远(例如,它们到达第一个路由器,可能是运行您家 LAN 的路由器,然后停在那里)。

因此,关于理想宇宙的所有信息似乎与这种情况无关。然而!我的怀疑是,大多数实现多播的人对第一部分的想法非常非常认真,并且在他们完成实现时已经很累了。

一旦多播组的消息实际到达主机,主机需要将其传递给实际对其感兴趣的程序。在这里,我怀疑,实施者太累了,无法做正确的事情。相反,他们做了各种懒惰、简单的事情(取决于你的平台)。例如,他们中的一些人只是访问了系统上订阅多播组的每个打开的套接字并将消息传递给他们。

在其他平台上,您有时会发现单个多播消息多次传递到单个侦听多播套接字。当然,还有一个流行的问题是多播消息根本不会被传递。

在多播领域享受您的古怪时光!

于 2012-07-28T10:56:41.650 回答