在 Linux 上接收 UDP 广播数据包

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13666789/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 17:56:18  来源:igfitidea点击:

Receiving UDP broadcast packets on Linux

linuxudpbroadcast

提问by goose

We have existing software that periodically broadcasts UDP packets to a specific port (7125) on the local subnet (x.x.x.255). We have monitoring software running on HP-UX (11.11) that is able to receive these packets no problem. However, after porting the monitoring software to Linux (RHEL 6.1) we have found that it does not receive the broadcast packets. tcpdump shows the packets arriving at the Linux host, but the kernel does not send them through to our software.

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

I've been using a couple of python 2.x scripts that mimic the socket API calls the monitoring software uses to test different scenarios. The Linux kernel passes the packets to the receiver software if the sender uses unicast (10.1.0.5), but not broadcast (10.1.0.255). I've been searching the web for several days and have not found anyone with the same problem. Any ideas?

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

receiver.py

接收器.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

发件人.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()

回答by Matthew Hall

Well, I suggested this answer in a comment, and it proved correct in practice. I would like to investigate surrounding nuances further with my own code, but this is the canonical case-closer.

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

In addition to setting the SO_BROADCASTsocket option on both sides (as you are already correctly doing), you must also bind your receiver to the broadcast address (e.g., INADDR_BROADCAST, which is 255.255.255.255 and essentially serves the same role as INADDR_ANYfor unicast).

除了SO_BROADCAST在两侧设置套接字选项(正如您已经正确执行的那样),您还必须将接收器绑定到广播地址(例如,INADDR_BROADCAST255.255.255.255 并且本质上与INADDR_ANY单播的作用相同)。

Apparently, in the HP-UX configuration of the original poster, a UDP socket bound to a unicast address (or INADDR_ANY, specifically) but with the SO_BROADCASTsocket option set will still receive all UDP datagrams addressed to the local broadcast address as well as unicast traffic directed at the host.

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

Under Linux, this is not the case. Binding a UDP socket, even when SO_BROADCAST-enabled, to INADDR_ANYis insufficient to receive both unicast and broadcast datagrams on the bound port. One can use a separate INADDR_BROADCAST-bound SO_BROADCASTsocket for the broadcast traffic.

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