简体   繁体   English

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

[英]Python twisted framework multicast bind on specific interface

After searching high and low across the google i have not found the definitive answer to the following question: by roughly following the following guide: http://twistedmatrix.com/documents/10.2.0/core/howto/udp.html#auto3 在google上搜索高低之后我还没有找到以下问题的明确答案:大致遵循以下指南: http//twistedmatrix.com/documents/10.2.0/core/howto/udp.html#auto3

How is it possible to bind twisted Multicast listener to ONLY the multicast address and on specific or all interfaces. 如何将双绞线多播侦听器绑定到多播地址以及特定或所有接口上。

While looking at reactor.listenMulticast it does not provide abstraction for hardware interface only an pseudo interface represented by an IP address. 在查看reactor.listenMulticast时,它不为硬件接口提供抽象,只提供由IP地址表示的伪接口。 I cant find a method to bind only on the multicast address eg 224.0.0.1 of a specific interface or all interfaces. 我找不到只绑定多播地址的方法,例如特定接口或所有接口的224.0.0.1。 Can anyone provide further information on this? 任何人都可以提供更多相关信息吗?

The other answers may solve the problem, but there is a "more twisted" (and probably easier) way to listen to a multicast group on multiple interfaces. 其他答案可以解决问题,但是在多个接口上监听多播组的方式有“更加扭曲”(并且可能更容易)。

Listening to a multicast group on one or more interfaces 在一个或多个接口上侦听多播组

To listen to a multicast group on one or more interfaces, provide the IP of each desired interface in multiple calls to the protocol's transport.joinGroup() method as the 'interface' argument. 要在一个或多个接口上侦听多播组,请在协议的transport.joinGroup()方法的多次调用中提供每个所需接口的IP作为“接口”参数。

Below is an example that works on my Linux box, and will make your system listen to multicasts on specific interfaces. 下面是一个适用于我的Linux机器的示例,它将使您的系统在特定接口上侦听多播。 Replace the IP addresses with ones belonging to your system. 将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()

You can check that the interface is listening to the new multicast group using the /sbin/ip maddr show command. 您可以使用/sbin/ip maddr show命令检查接口是否正在侦听新的多播组。 Find the desired interface name in the command output, and verify that the multicast group shows up beneath it. 在命令输出中找到所需的接口名称,并验证多播组是否显示在其下方。

The UDP Server example linked in the original post should be able to do the same thing by changing the call to joinGroup() to include the second IP address argument, as above. 原始帖子中链接的UDP服务器示例应该能够通过更改对joinGroup()的调用来包含第二个IP地址参数来执行相同的操作,如上所述。

Sending multicasts from a particular IP 从特定IP发送多播

If you're receiving multicast data on a socket, chances are you will want to send multicast data too -- possibly out of multiple interfaces. 如果您正在接收套接字上的组播数据,那么您可能也希望发送多播数据 - 可能是多个接口。 Since it's closely related and there are very few examples around I'll throw it in here. 由于它密切相关,并且我将把它放在这里的例子很少。 Inside a twisted.internet.protocol.DatagramProtocol object you can use the self.transport.setOutgoingInterface() method to control the source IP that will be used for subsequent calls to self.transport.write(). 在twisted.internet.protocol.DatagramProtocol对象中,您可以使用self.transport.setOutgoingInterface()方法来控制将用于后续调用self.transport.write()的源IP。 Example showing sending a message from multiple IPs/interfaces: 显示从多个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))

Suppose these IPs were assigned to two different interfaces. 假设这些IP分配给两个不同的接口。 Sniffing with Wireshark you would see the message sent out of the first interface, then the second interface, using each IP as a source IP address for the respective transmission. 使用Wireshark嗅探您会看到从第一个接口发出的消息,然后是第二个接口,使用每个IP作为相应传输的源IP地址。

reactor.listenMulticast returns a twisted.internet.udp.MulticastPort object. reactor.listenMulticast返回twisted.internet.udp.MulticastPort对象。 That object owns the socket you're listening on. 该对象拥有您正在侦听的套接字。 So hang on to the result of reactor.listenMulticast and set the appropriate socket option (in this case it looks like SO.BINDTODEVICE) along with a null terminated device string. 因此,请继续查看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()

It would be nice if this were exposed directly through the listenMulticast call but assuming this works it would be a pretty easy patch. 如果直接通过listenMulticast调用公开它会很好,但假设这有效,那将是一个非常简单的补丁。 Let me know if this solves your problem. 如果这可以解决您的问题,请告诉我。

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

sudo route add 239.255.0.0 -interface en0 -netmask 255.255.0.0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM