无法在Python中接收UDP数据包

1 投票
1 回答
3649 浏览
提问于 2025-04-28 03:23

我在用Python程序接收从FPGA发送的UDP数据包时遇到了问题。我查看了类似的问题,并做了以下几件事:

  • 确认Wireshark可以看到UDP数据包
  • 关闭了电脑上的Windows防火墙
  • 因为是UDP数据包,所以使用了sock.bind()
  • 手动在以太网帧中设置了目标MAC地址,因为FPGA不支持ARP
  • 为了测试,将目标IP设置为广播地址10.10.255.255,但没有收到任何数据包
  • 将发送方的数据包的UDP校验和设置为0x0000

这是接收端的Python代码:

import socket
import sys

UDP_IP = "10.10.10.87"
UDP_PORT = 4660

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
print("Socket: "+str(sock.getsockname()))
while True:
    data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
    print(data)
    print(addr)
    sys.stdout.flush()

当我用另一个Python脚本向10.10.10.87:4660发送数据(来自10.10.10网络中的另一台电脑)时,接收脚本运行得很好。我甚至尝试在FPGA中逐字节重建UDP数据包,使用的是我知道可以正常接收的数据包(不同之处在于源IP、端口和MAC地址,校验和被禁用,标识符也不同)。

这是Wireshark对两个数据包的输出:

Wireshark UDP数据包(左边是Python UDP数据包,正常接收;右边是Xilinx FPGA数据包,Python没有接收到)

我不确定还可以尝试什么。任何帮助都将不胜感激。

暂无标签

1 个回答

2

看起来,FPGA计算出来的IPv4头部的校验和是错误的。这个过程可能会让人感到困惑,因为在路由器跳转时,TTL(生存时间)会发生变化,而新的TTL也会改变IPv4头部,这就意味着每经过一个路由器,校验和都需要重新计算,直到数据包到达接收端的Wireshark。默认情况下,Wireshark是关闭IPv4校验和验证的(在问题的截图中可以看到),如果开启验证,问题就更容易发现了。

在构建数据包时,我把IPv4校验和设置为零(x0000)。在路由器那里,它会被正确地重新计算,并且有了正确的校验和,Python就能接收到这个数据包。

我还测试了一个直接连接(没有路由器)从FPGA到主机电脑的情况。IPv4头部也会被正确地重新计算(我不太确定是在什么地方,可能是在电脑的网卡上?)

希望这些信息对遇到类似问题的人有帮助。

撰写回答