我在尝试使用setsockopt()
设置不同的IP_MTU_DISCOVER
值对udp包碎片的影响,发现(从man
页,共ip(7)
)我需要将其值设置为IP_PMTUDISC_WANT
或IP_PMTUDISC_DONT
以关闭“不分段”标志。但是,当我尝试发送数据包时,我得到socket.error: [Errno 90] Message too long
。在
import IN, socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
hostname = 'localhost'
s.connect((hostname, 1060))
s.setsockopt(socket.IPPROTO_IP, IN.IP_MTU_DISCOVER, IN.IP_PMTUDISC_DONT)
mtu = s.getsockopt(socket.IPPROTO_IP, IN.IP_MTU)
print 'MTU:', mtu
s.send('.' * (mtu + 1))
print 'Big packet sent'
谢谢你
让我们首先回顾一下PMTU是如何为UDP工作的。在
ICMP Destination Unreachable
包,错误代码为4,并返回下一个跃点MTU。在需要注意的是,PMTU不会自动发生。在您(应用程序)开始发送实际数据之前,没有内置的探测包可以找到MTU。在
因此,Linux使用以下标志控制(对于数据报):
IP_PMTUDISC_WANT
执行上述PMTU。如果应用程序发送的数据包对于已知的MTU来说太大了,套接字层将对其进行分段。传出数据包(包括碎片)将设置DF位。在IP_PMTUDISC_DONT
不要执行PMTU发现。在IP_PMTUDISC_DO
做PMTU发现。如果应用程序发送的数据包对于已知MTU来说太大,则向应用程序发送错误。在IP_PMTUDISC_PROBE
设置DF位以执行PMTU发现,但忽略当前学习的MTU。因此,如果应用程序发送的数据包太大,它无论如何都会尝试将其发送出去。这有助于不时地发送一个探测器,看看PMTU是否没有增加。在现在需要注意的一点是,
IP_PMTUDISC_DONT
没有指定如果数据包实际上大于当前MTU(即直接链接的MTU)时该怎么做。所以最有可能的是,这个选择由接口来决定,接口实际上必须发送数据包。由于DF位没有被发送,大多数接口实际上应该对包进行分段。但是,您使用的是链接本地接口,它通常是一个功能稍差的软件接口。在您的发行版中,这可能不支持碎片,因此发送错误。这很有道理,从我的机器上取下这个输出:这表明链路本地接口的MTU在网络方面是相当巨大的,那么它为什么要从支持碎片化开始呢。也就是说,在我的系统中,这实际上运行得很好。在
相关问题 更多 >
编程相关推荐