Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
查找最大UDP负载--python套接字发送/发送到_Python_Sockets_Networking_Udp - Fatal编程技术网

查找最大UDP负载--python套接字发送/发送到

查找最大UDP负载--python套接字发送/发送到,python,sockets,networking,udp,Python,Sockets,Networking,Udp,如何在Python(Python 2)中找到UDP有效负载的最大长度,最好是独立于平台的 具体来说,我希望避免[Errno 90]消息太长AKAErrno.EMSGSIZE 背景 UDP数据包格式允许的最大值) IPv4数据包格式允许的最大值 但似乎是这样 我不是在问什么 ? 一个IPv4数据报可以容纳的最大UDP负载是多少 一个以太网帧可以容纳的最大UDP负载是多少 演示代码 要查看操作中的错误,请执行以下操作: import socket msg_len = 65537 # No

如何在Python(Python 2)中找到UDP有效负载的最大长度,最好是独立于平台的

具体来说,我希望避免
[Errno 90]消息太长
AKA
Errno.EMSGSIZE

背景
  • UDP数据包格式允许的最大值)
  • IPv4数据包格式允许的最大值

  • 但似乎是这样

我不是在问什么
  • ?
  • 一个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))

嗯,总有一种“试一试”的方法。。。我不认为这很优雅,但它是平台独立的:

import socket

def canSendUDPPacketOfSize(sock, packetSize):
   ip_address = "127.0.0.1"
   port = 5005
   try:
      msg = "A" * packetSize
      if (sock.sendto(msg, (ip_address, port)) == len(msg)):
         return True
   except:
      pass
   return False

def get_max_udp_packet_size_aux(sock, largestKnownGoodSize, smallestKnownBadSize):
   if ((largestKnownGoodSize+1) == smallestKnownBadSize):
      return largestKnownGoodSize
   else:
      newMidSize = int((largestKnownGoodSize+smallestKnownBadSize)/2)
      if (canSendUDPPacketOfSize(sock, newMidSize)):
         return get_max_udp_packet_size_aux(sock, newMidSize, smallestKnownBadSize)
      else:
         return get_max_udp_packet_size_aux(sock, largestKnownGoodSize, newMidSize)

def get_max_udp_packet_size():
   sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
   ret = get_max_udp_packet_size_aux(sock, 0, 65508)
   sock.close()
   return ret

print "Maximum UDP packet send size is", get_max_udp_packet_size()

嗯,总有一种“试一试”的方法。。。我不认为这很优雅,但它是平台独立的:

import socket

def canSendUDPPacketOfSize(sock, packetSize):
   ip_address = "127.0.0.1"
   port = 5005
   try:
      msg = "A" * packetSize
      if (sock.sendto(msg, (ip_address, port)) == len(msg)):
         return True
   except:
      pass
   return False

def get_max_udp_packet_size_aux(sock, largestKnownGoodSize, smallestKnownBadSize):
   if ((largestKnownGoodSize+1) == smallestKnownBadSize):
      return largestKnownGoodSize
   else:
      newMidSize = int((largestKnownGoodSize+smallestKnownBadSize)/2)
      if (canSendUDPPacketOfSize(sock, newMidSize)):
         return get_max_udp_packet_size_aux(sock, newMidSize, smallestKnownBadSize)
      else:
         return get_max_udp_packet_size_aux(sock, largestKnownGoodSize, newMidSize)

def get_max_udp_packet_size():
   sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
   ret = get_max_udp_packet_size_aux(sock, 0, 65508)
   sock.close()
   return ret

print "Maximum UDP packet send size is", get_max_udp_packet_size()

你的一些前提需要一个小的修正

由于IP报头包含一个16位的长度字段,IPv4消息的最大大小可以是
65535
字节,其中包括IP报头本身

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

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

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

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


我建议您使用Wireshark运行代码,并将其发送到网络外的真实IP地址。您可以观察和研究IP碎片是如何工作的。

您的一些前提需要进行轻微的更正

由于IP报头包含一个16位的长度字段,IPv4消息的最大大小可以是
65535
字节,其中包括IP报头本身

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

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

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

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


我建议您使用Wireshark运行代码,并将其发送到网络外的真实IP地址。你可以观察和研究IP碎片是如何工作的。

相关:我认为没有一种便携的方式来获取这些信息。这不是socket API的一个特性。相关:我认为没有一种可移植的方式来获取这些信息。这不是socket API的一个特性。“碎片对应用程序是透明的。”这是真的,但碎片和重新组装需要时间。此外,许多路由器和大多数防火墙只允许第一个碎片通过,因为碎片用于攻击。如果整体的任何一个片段丢失,则整个将被丢弃。碎片真的不再实用了。Ron,我正要写一些关于IP碎片可靠性问题的类似细节,以及为什么在UDP字段中重载太多数据不是一个好主意。现代路由器会限制碎片的数量是可以理解的,但如果它将碎片数量限制为1,我会非常惊讶。(但是,嘿,我每天都学到一些新东西。)我更多的是写关于目标路由器或防火墙的文章。默认情况下,大多数防火墙不再允许碎片。企业通常在路由器上配置相同的东西。我总是很惊讶,人们希望用尽可能多的数据加载不可靠的协议,知道丢失一个数据包会丢失更多的数据。谢谢Ron。事实上,我很好奇要测试这个,因为我坚持。但是我还没有实现对的PADDING属性支持,因为我从来没有看到它的必要性(以及一些公共服务器的安全问题)。测试我所使用的各种网络会很有趣。“碎片对应用程序是透明的。”这是真的,但碎片和重组需要时间。而且,许多路由器和大多数防火墙只允许第一个片段通过,因为fragmen