python - 确定最大 UDP 数据报大小的跨平台方法
问题描述
我正在尝试提高发送 UDP 数据报的 Python 程序的可移植性。
在 BSD 和 macOS 上,它访问net.inet.udp.maxdgram
sysctl 以确定它可以在一个数据包中传输的最大字节数。(在我的 macOS 11.2 系统上,该值返回 9216。)Linux 上不存在此 sysctl。
有一个套接字选项SO_SNDBUF
指示内核分配的发送缓冲区的大小。我可以检查它:
import socket
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
max_dgram = s.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
在 macOS 上,这返回相同的值 9216。但在 Linux 上,它返回 212992,这对于单个 UDP 数据包来说似乎太大了,所以我认为SO_SNDBUF
查询不是正确的。
(另外,文档SO_SNDBUF
说,“这个限制是计算为两倍的......选项值减去用于开销的 32 个字节。”这意味着实际的最大大小接近半兆字节。)
有没有办法做到这个跨平台?或者如果不是,在 Linux 上做这件事的正确方法是什么?
解决方案
SO_SNDBUF 很大,因为 udp 可以分片。
似乎 9216 是 2^13(最后一个片段偏移)+ 1024(安全有效负载大小)
Linux 212992 是 /proc/sys/net/core/wmem_max 因为您可以在一个套接字上同时将数据包发送到几个或多个目的地,但对于 SOCK_STREAM 它加倍 2^13
如果客户端 IP 堆栈支持 ICMP,请使用https://stackoverflow.com/a/26524829/2101808 PMTU 发现。或者通过发送带有 DF 标志的数据包在应用层执行此操作。
推荐阅读
- makefile - 我遇到了制作文件的问题
- python - GAN 中的生成器是如何工作的?
- java - 如何使用spring boot / java将json对象存储在mysql的列中
- linux - 树莓派零蓝牙连接到设备失败
- macos - 如何在 macOS 上安装 bazelisk?
- java - 发布映射注释在springboot上不起作用
- python - 在 Pandas 中计算整个数据框中特定字符串的数量并将其值添加到新列中
- swift5 - ITMS-90429:无效的 Swift 支持 - 文件 libswiftDarwin.dylib、libswiftMetal.dylib、
- google-sheets - 在行中查找最大值
- websphere - 关于ejbs上xa和事务的问题