在Linux上接收UDP广播数据包



我们现有的软件可以定期将UDP数据包广播到本地子网(x.x.x.255)上的特定端口(7125)。我们有在HP-UX(11.11)上运行的监控软件,可以毫无问题地接收这些数据包。但是,在将监控软件移植到Linux(RHEL 6.1)之后,我们发现它不会接收广播数据包。tcpdump显示到达Linux主机的数据包,但内核不会将它们发送到我们的软件。

我一直在使用两个python 2.x脚本,它们模仿监控软件用来测试不同场景的socket API调用。如果发送方使用单播(10.1.0.5),但不使用广播(10.1.0.255),Linux内核会将数据包传递给接收方软件。我已经在网上搜索了几天,没有发现有同样问题的人。有什么想法吗?

接收者.py

from __future__ import print_function
import socket
localHost = ''
localPort = 7125
remoteHost = '10.1.0.5'
remotePort = 19100
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.bind((localHost, localPort))
s.connect((remoteHost, remotePort))
print('Listening on {0}:{1} for traffic from {2}:{3}'.format(localHost, localPort, remoteHost, remotePort))
data = s.recv(1024)
print('Received: {0}'.format(data))
s.close()

sender.py

from __future__ import print_function
import socket
import time
localHost = ''
localPort = 19100
remoteHost = '10.1.0.255'
remotePort = 7125
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.bind((localHost, localPort))
s.connect((remoteHost, remotePort))
data = 'sending this from {0}:{1} to {2}:{3}'.format(localHost, localPort, remoteHost, remotePort)
print(data)
print('2')
time.sleep(1)
print('1')
time.sleep(1)
s.send(data)
print('sent at {0}'.format(time.ctime()))
s.close()

好吧,我在一条评论中提出了这个答案,实践证明它是正确的。我想用我自己的代码进一步研究周围的细微差别,但这是更接近规范的情况。

除了在两侧设置SO_BROADCAST套接字选项(正如您已经正确地做的那样),您还必须将接收器绑定到广播地址(例如,INADDR_BROADCAST,其为255.255.255,基本上与单播的INADDR_ANY起相同的作用)。

显然,在原始海报的HP-UX配置中,绑定到单播地址(特别是INADDR_ANY)但设置了SO_BROADCAST套接字选项的UDP套接字仍将接收寻址到本地广播地址的所有UDP数据报以及指向主机的单播流量。

在Linux下,情况并非如此。即使启用了SO_BROADCAST,将UDP套接字绑定到INADDR_ANY也不足以在绑定端口上接收单播和广播数据报。可以使用单独的绑定了INADDR_BROADCASTSO_BROADCAST套接字来接收广播流量。

最新更新