Python 为什么不是';";不要断章取义;国旗被禁用了?
我正在尝试使用Python 为什么不是';";不要断章取义;国旗被禁用了?,python,sockets,python-2.7,Python,Sockets,Python 2.7,我正在尝试使用setsockopt()对udp数据包碎片设置不同的IP_MTU_DISCOVER值的效果,并发现(从man页面的IP(7))我需要将其值设置为IP_PMTUDISC\u WANT或IP_PMTUDISC\u DONT以关闭“不碎片”标志。但是,当我尝试发送数据包时,我收到的socket.error:[Errno 90]消息太长 import IN, socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) hostn
setsockopt()
对udp数据包碎片设置不同的IP_MTU_DISCOVER
值的效果,并发现(从man
页面的IP(7)
)我需要将其值设置为IP_PMTUDISC\u WANT
或IP_PMTUDISC\u DONT
以关闭“不碎片”标志。但是,当我尝试发送数据包时,我收到的socket.error:[Errno 90]消息太长
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工作的
IP端点以给定的MTU开始,通常是其直接连接链路的MTU
发送数据包时,端点始终设置DF位
如果中转路由器决定在不分割数据包的情况下无法发送数据包,它将返回一个ICMP目的地不可到达
数据包,错误代码为4和下一跳MTU
IP端点接收无法访问的ICMP并调整其PMTU
IP端点决定如何处理原始数据包(重传、信号应用层等)
这里需要特别注意的是,PMTU不会自动发生。在您(应用程序)开始发送实际数据之前,没有内置的探测数据包可以找到MTU
因此Linux使用以下标志来控制(数据报):
IP_PMTUDISC_WANT
执行上述PMTU。如果应用程序发送的数据包对于已知的MTU来说太大,套接字层将对其进行分段。传出数据包(包括片段)将设置DF位
IP\u PMTUDISC\u DONT
不要执行PMTU发现
IP\u PMTUDISC\u DO
DO PMTU发现。如果应用程序发送的数据包对于已知MTU来说太大,则向应用程序发送错误李>
IP_PMTUDISC_PROBE
将DF位设置为执行PMTU发现,但忽略当前学习的MTU。因此,如果应用程序发送的数据包太大,它将尝试发送出去。这有助于不时发送探测器,查看PMTU是否增加
现在需要注意的是,IP\u PMTUDISC\u DONT
没有指定如果数据包实际大于您当前的MTU(即您的直接链接的MTU),该怎么办。因此,最有可能的情况是,它将这个选择留给实际必须发送数据包的接口。由于DF位没有发送,大多数接口实际上应该对数据包进行分段。但是,您使用的是link-local接口,它通常是一个功能稍差的软件接口。在您的发行版上,这可能不支持碎片,因此会发送错误。这很有意义,从我的机器上获取以下输出:
In [6]: s.getsockopt(socket.IPPROTO_IP, 14) #14 = IP_MTU, just wasn't in my python lib.
Out[6]: 16436
这表明链路本地接口的MTU在网络方面是相当大的,那么为什么要从支持碎片开始呢。也就是说,在我的系统上,这实际上运行得很好。当我将IP\u PMTUDISC\u DONT
替换为IP\u PMTUDISC\u WANT
时,会出现相同的错误,为什么?它应该会把包裹弄碎,对吗?你看过我的全部答案了吗?最后,我指定了独立于该设置的碎片可能出现的问题。