Jetson Xavier上Python Socket无法读取UDP数据包问题排查
问题描述
通过以太网发送UDP广播数据包到2368端口,Python 3.8.10的socket代码在MacOS Monterey 12.5.1上能正常接收,但在Jetson Xavier(Ubuntu 20.04.5 LTS)上soc.recv(2000)持续阻塞,无法读取数据包。尽管tcpdump显示Jetson已捕获到数据包,但Python程序无法获取。
使用的Python代码:
import socket with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as soc: soc.bind(("", 2368)) data = soc.recv(2000) # 采用任意缓冲区大小 print("Received Data!", data)
排查与解决建议
1. 开启Socket的广播接收权限
默认情况下,Linux的UDP socket可能未开启广播接收能力,需要显式设置*SO_BROADCAST*选项:
import socket with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as soc: soc.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) soc.bind(("", 2368)) data = soc.recv(2000) print("Received Data!", data)
2. 检查网卡的广播配置
运行以下命令查看Jetson的以太网网卡(比如eth0)是否开启广播:
ip addr show eth0
确认输出中包含BROADCAST标志,类似:inet 192.168.1.x/24 brd 192.168.1.255 scope global eth0。如果没有,重新配置网卡启用广播:
sudo ip link set eth0 broadcast 192.168.1.255
3. 绑定到具体的本地IP而非通配符
尝试将socket绑定到Jetson的以太网IP(比如192.168.1.x),而不是通配符"":
import socket with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as soc: soc.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) soc.bind(("192.168.1.x", 2368)) # 替换为实际IP data = soc.recv(2000) print("Received Data!", data)
4. 检查内核的广播过滤参数
Linux内核可能存在广播数据包过滤,检查以下参数:
sysctl net.ipv4.conf.eth0.broadcast_forwarding sysctl net.ipv4.conf.all.broadcast_forwarding
如果值为0,改为1:
sudo sysctl -w net.ipv4.conf.eth0.broadcast_forwarding=1 sudo sysctl -w net.ipv4.conf.all.broadcast_forwarding=1
5. 用socat测试端口可用性
先排除Python代码问题,用socat直接监听2368端口的UDP广播:
socat UDP-RECV:2368,broadcast -
发送数据包后看是否能接收到,如果可以,说明是Python代码的配置问题;如果不行,继续排查系统层面的网络设置。
tcpdump输出差异解释
broadcasthost vs 255.255.255.255
broadcasthost是MacOS系统中对广播地址255.255.255.255的主机名映射(在/etc/hosts中定义),而Jetson的tcpdump直接显示原始的广播IP地址,两者本质是同一个地址,没有功能差异。
opentable vs 2368
opentable是端口号2368对应的服务名,来源于/etc/services文件。MacOS的tcpdump默认会将端口号解析为服务名,而Jetson的tcpdump默认直接显示端口号。你可以在Jetson上运行tcpdump -n来禁用端口解析,就会和Mac的输出格式更一致(只显示端口号)。
内容的提问来源于stack exchange,提问作者dinodeep

