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

发布于 2024-10-29 18:10:54 字数 371 浏览 0 评论 0原文

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

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

在查看reactor.listenMulticast时,它不提供硬件接口的抽象,仅提供由IP地址表示的伪接口。我找不到仅绑定到特定接口或所有接口的多播地址(例如 224.0.0.1)的方法。 谁能提供这方面的进一步信息?

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

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. I cant find a method to bind only on the multicast address e.g. 224.0.0.1 of a specific interface or all interfaces.
Can anyone provide further information on this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

(り薆情海 2024-11-05 18:10:55

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

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 调用公开那就太好了,但假设这有效,那将是一个非常简单的补丁。如果这可以解决您的问题,请告诉我。

reactor.listenMulticast returns a twisted.internet.udp.MulticastPort object. 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.

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. Let me know if this solves your problem.

沧笙踏歌 2024-11-05 18:10:55

其他答案可能会解决问题,但有一种“更扭曲”(可能更简单)的方法来侦听多个接口上的多播组。

侦听一个或多个接口上的多播组

要侦听一个或多个接口上的多播组,请在对协议的 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 地址。

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.

Below is an example that works on my Linux box, and will make your system listen to multicasts on specific interfaces. Replace the IP addresses with ones belonging to your system.

#!/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. 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.

Sending multicasts from a particular 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(). Example showing sending a message from multiple IPs/interfaces:

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

秋日私语 2024-11-05 18:10:55

一种简单但严厉的方法可能是通过以下方式指定路线:

sudo route add 239.255.0.0 -interface en0 -netmask 255.255.0.0

A simple, if heavy handed approach could be to just specify a route via something like:

sudo route add 239.255.0.0 -interface en0 -netmask 255.255.0.0
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文