2012-12-02 63 views
10

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

我一直在使用模拟套接字API的几个python 2.x脚本来调用监视软件用来测试不同的场景。如果发送方使用单播(10.1.0.5),而不是广播(10.1.0.255),则Linux内核将数据包传递给接收方软件。我一直在网上搜索几天,并没有发现任何人有同样的问题。有任何想法吗?

receiver.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() 
+2

您的接收器是否需要“绑定”广播地址或“INADDR_BROADCAST”(255.255.255.255,广播的“INADDR_ANY”)?也就是说,除了设置'SO_BROADCAST'选项(双方)之外,就像你已经做的那样。您是否检查所有这些套接字系统调用的错误/返回代码? –

+0

@MatthewHall aha,绑定到广播地址确实有效!我想这意味着Linux会让你选择单播还是广播?我们可以绑定到INADDR_ANY,并在HP-UX上接收单播和广播数据包。 – goose

+0

是的,这似乎是你必须选择。我现在已经为你的问题发布了一个规范的答案。然而,我对Linux上的行为与HP-UX的行为有所不同有些困惑(尽管有人争辩说为什么分离广播和单播更可取)。对我而言,这表明我们并不知道所有事情,嗯,这是不可接受的。我很想用C编写一对测试程序来充实Linux上的广播选项,尽管我没有HP-UX ......在此之前,希望我的答案能够涵盖它。 –

回答

13

好吧,我建议在评论这个答案,并在实践中证明是正确的。我想用我自己的代码进一步调查周围的细微差别,但这是规范的情况。

除了设置在两侧的SO_BROADCAST套接字选项(因为你已经做正确),则还必须绑定您的接收到广播地址(例如,INADDR_BROADCAST,这是255.255.255.255,基本上起到同样的作用作为单播的INADDR_ANY)。

显然,在原来的海报,绑定到单播地址(或INADDR_ANY,特别是)一个UDP套接字的HP-UX配置,但是与SO_BROADCAST套接字选项组仍然将接收所有的UDP数据报给当地的广播地址以及针对主机的单播流量。

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

+3

我们的解决方案实际上是绑定到子网广播地址,而不是'INADDR_BROADCAST'。另外,我们运行一个模拟环境,我们希望接收单播而不是广播,所以这不是最终的解决方案。但是,如果您编辑了'INADDR_BROADCAST',我会点击复选标记。 – goose

+0

出于好奇,这是记录在任何地方吗? – Clay