Python扭曲的框架多播绑定在特定的接口上

时间:2011-03-31 10:49:43

标签: python interface twisted multicast

在谷歌搜索高低之后我还没有找到以下问题的明确答案: 大致遵循以下指南: http://twistedmatrix.com/documents/10.2.0/core/howto/udp.html#auto3

如何将扭曲的多播侦听器绑定到 ONLY 多播地址以及特定或所有接口上。

在查看reactor.listenMulticast时,它不为硬件接口提供抽象,只提供由IP地址表示的伪接口。我找不到一种只在多播地址上绑定的方法,例如224.0.0.1的特定接口或所有接口。 任何人都可以提供更多相关信息吗?

3 个答案:

答案 0 :(得分:3)

reactor.listenMulticast会返回twisted.internet.udp.MulticastPort个对象。该对象拥有您正在侦听的套接字。因此,请继续查看reactor.listenMulticast的结果,并设置相应的套接字选项(在本例中,它看起来像SO.BINDTODEVICE)以及一个以null结尾的设备字符串。

import IN, socket, struct

udp_port = reactor.listenMulticast(8005, MulticastServerUDP())
dev = "eth0" + "\0"
udp_port.socket.setsockopt(socket.SOL_SOCKET, IN.SO_BINDTODEVICE, dev)
reactor.run()

如果通过listenMulticast调用直接公开它会很好,但假设这有效,那将是一个非常简单的补丁。如果这可以解决您的问题,请告诉我。

答案 1 :(得分:3)

其他答案可能会解决问题,但在多个界面上监听多播组的方式有“更加扭曲”(可能更容易)。

在一个或多个界面上侦听多播组

要在一个或多个接口上侦听多播组,请在协议的transport.joinGroup()方法的多次调用中提供每个所需接口的IP作为“接口”参数。

下面是一个适用于我的Linux机器的示例,它将使您的系统在特定接口上侦听多播。将IP地址替换为属于您系统的IP地址。

#!/usr/bin/env python

from twisted.internet import protocol
from twisted.internet import reactor

class MyProtocol(protocol.DatagramProtocol):
    def startProtocol(self):
        # Join a multicast group, 224.0.0.9, on the interface belonging
        # to each of these IPs.
        # XXX Replace the interface_ips with one or more IP addresses belonging
        # to your system.
        for interface_ip in ["192.168.2.2", "10.99.1.100"]:
            self.transport.joinGroup("224.0.0.9", interface_ip)

if __name__ == "__main__":
    reactor.listenMulticast(1520, MyProtocol())
    reactor.run()

您可以使用/sbin/ip maddr show命令检查接口是否正在侦听新的多播组。在命令输出中找到所需的接口名称,并验证多播组是否显示在其下方。

原始帖子中链接的UDP服务器示例应该能够通过更改对joinGroup()的调用来包含第二个IP地址参数来执行相同的操作,如上所述。

从特定IP发送多播

如果您在套接字上接收多播数据,您可能也希望发送多播数据 - 可能是多个接口。由于它密切相关,并且我将把它放在这里的例子很少。在twisted.internet.protocol.DatagramProtocol对象中,您可以使用self.transport.setOutgoingInterface()方法来控制将用于后续调用self.transport.write()的源IP。显示从多个IP /接口发送消息的示例:

class MyProtocol(protocol.DatagramProtocol):
    # ...
    def send_stuff(self, msg):
        for src_ip in ["10.0.0.1", "192.168.1.1"]:
            self.transport.setOutgoingInterface(src_ip)
            self.transport.write(msg, ("224.0.0.9", 1520))

假设这些IP分配给两个不同的接口。使用Wireshark嗅探您会看到从第一个接口发出的消息,然后是第二个接口,使用每个IP作为相应传输的源IP地址。

答案 2 :(得分:1)

一个简单的,如果重手的方法可以通过类似的方式指定路线:

sudo route add 239.255.0.0 -interface en0 -netmask 255.255.0.0