Skip to main content
 首页 » 编程设计

python之查找最大 UDP 负载——python socket send/sendto

2025年05月04日26cloudgamer

如何在 Python (Python 2) 中找到 UDP 负载的最大长度,最好与平台无关?

具体来说,我想避免 [Errno 90] Message too long 又名 errno.EMSGSIZE。

背景

我没有问什么

演示代码

要查看操作中的错误:

import socket 
 
msg_len = 65537  # Not even possible! 
 
ip_address = "127.0.0.1" 
port = 5005 
msg = "A" * msg_len 
 
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
sock.sendto(msg, (ip_address, port)) 

请您参考如下方法:

您的一些场所需要进行小的更正。

由于 IP header 包含 16 位长度字段,因此 IPv4 消息的最大大小可以是 65535 字节,其中包括 IP header 本身。

IP 数据包本身至少有一个 20 字节的 header 。因此 65535 - 20 == 65515 是 IP 消息的最大有效载荷。负载可以是 UDP 数据报。

UDP 数据报本身通常是一个 8 字节的报头。因此 65515 - 8 == 65507。因此,即使 UDP header 理论上可以在其自身的长度字段中包含大于 65507 的数量,IPv4 消息也不能包含它。

但如果您的系统向 IP header 添加更多 header (通过套接字 ioctls 或其他方式的选项字段),则 UDP 应用程序有效负载的限制将相应减少。

实际上,任何超过网络适配器 MTU 大小(~1500 字节)的 IP 消息都会触发 UDP 数据包进行 IP 分段。因此,如果您的以太网卡具有 1500 字节的消息大小,则包含 65507 字节应用程序数据的 UDP 数据报将被分成大约 43 个独立的以太网帧。每个帧都是一个分段的 IP 数据包,其中包含 UDP 字节的子集,但具有单独的 header 。当远程端接收到所有 IP 片段时,它在逻辑上将作为 65507 字节数据报传递给应用程序。碎片对应用程序是透明的。

我建议使用 Wireshark 运行您的代码并发送到网络外的真实 IP 地址。您可以观察和研究 IP 分片的工作原理。