如何在 Python (Python 2) 中找到 UDP 负载的最大长度,最好与平台无关?
具体来说,我想避免 [Errno 90] Message too long 又名 errno.EMSGSIZE。
背景
- UDP数据包格式允许的最大值is 65536 ).
IPv4数据包格式允许的最大值seems to be 65507 .
我没有问什么
- What is the largest Safe UDP Packet Size on the Internet ?
- 可以容纳在一个 IPv4 数据报中的最大 UDP 负载是多少?
- 可以容纳在一个以太网帧中的最大 UDP 负载是多少?
演示代码
要查看操作中的错误:
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 分片的工作原理。
