在 Linux 上接收 UDP 广播数据包 [英] Receiving UDP broadcast packets on Linux

查看:23
本文介绍了在 Linux 上接收 UDP 广播数据包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

我一直在使用几个 python 2.x 脚本来模拟监控软件用来测试不同场景的套接字 API 调用.如果发送方使用单播 (10.1.0.5) 而不是广播 (10.1.0.255),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?

receiver.py

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()

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

推荐答案

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

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.

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

In addition to setting the SO_BROADCAST socket 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_ANY for unicast).

显然,在原始海报的 HP-UX 配置中,UDP 套接字绑定到单播地址(或 INADDR_ANY,具体而言)但带有 SO_BROADCAST 套接字选项set 仍将接收所有发往本地广播地址的 UDP 数据报以及指向主机的单播流量.

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_BROADCAST socket option set will still receive all UDP datagrams addressed to the local broadcast address as well as unicast traffic directed at the host.

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

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

这篇关于在 Linux 上接收 UDP 广播数据包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆