使用Twisted Python在特定接口上接收广播UDP



我在Ubuntu 14.04服务器上工作,该服务器在不同的子网上有多个接口。我正在尝试编写一个扭曲的(13.2.0)应用程序,它只在一个接口上侦听广播,而忽略其他接口。

我可以用这个代码接收广播。

from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
import IN, socket, struct

class BroadcastListener(DatagramProtocol):
    def startProtocol(self):
        self.transport.getHandle().setsockopt(socket.SOL_SOCKET,
                                       socket.SO_BROADCAST, True)
    def datagramReceived(self, datagram, address):
        print "Received datagram from %s" % (address[0])
#reactor.listenUDP(65001, BroadcastListener(), interface='192.168.1.1')
reactor.listenUDP(3200, BroadcastListener())
reactor.run()

我正在用socat从192.168.1.x子网上的另一台机器发送测试UDP广播。

echo Hi |socat -  UDP-DATAGRAM:192.168.1.255:3200,broadcast

但是,这将在服务器上的任何接口上接收广播。我以为它会指定reactor.listenUDP()中的接口,就像我进行评论调用一样。

如果我使用包含接口的reactor.listenUDP()调用,我将不再接收广播。我仍然收到socat发送的单播UDP。

echo Hi |socat -  UDP-DATAGRAM:192.168.1.1:3200

当指定接口时,我可以看到套接字绑定到接口。

$ netstat -an |grep udp |grep 3200
udp        0      0 10.10.0.1:3200          0.0.0.0:*

但广播正在被取消。我用tcpdump确认广播正在到达服务器。

在twistedpython中设置UDP侦听器接口的正确方法是什么?

我假设您在这里使用Linux。bind()似乎不起作用,因为它丢弃了未寻址到接口的数据包,而对于广播数据包来说,接口就是所有数据包。相反,请尝试套接字选项SO_BINDTODEVICE,它可能不在您的Python socket模块中,但在我的Linux系统上,可能在您的Linux系统中具有值25(请检查/usr/include/asm-generic/socket.h)。它需要一个接口名称而不是IP地址,所以它应该看起来像这样:

self.transport.getHandle().setsockopt(socket.SOL_SOCKET, 25, "eth0")

最新更新