3

我正在使用在不同子网上有多个接口的 Ubuntu 14.04 服务器。我正在尝试编写一个 twisted(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 确认广播正在到达服务器。

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

4

1 回答 1

1

I'm assuming you're on Linux here. It seems that bind() won't work because it drops packets not addressed to the interface, which for broadcast packets is all of them. Instead, try the socket option SO_BINDTODEVICE, which may not be in your Python socket module, but has the value 25 on my Linux system and probably on yours (check /usr/include/asm-generic/socket.h). It takes an interface name rather than an IP address, so it should look something like this:

self.transport.getHandle().setsockopt(socket.SOL_SOCKET, 25, "eth0")
于 2015-02-04T04:36:30.440 回答