我读过许多关于UDP数据包大小的文章,但一直无法得出正确的结论。
许多服务将最大的UDP数据包限制在512字节(如dns)
假定internet上的最小MTU是576,IPv4报头的大小是20字节,UDP报头的大小是8字节。这就为用户数据留下了548个字节可用
我是否能够使用548大小的数据包而不产生数据包碎片?或者DNS的创造者知道一些事情,这就是为什么他们把它限制在512字节。
我能安全的把数据设置在548字节以上吗?
我读过许多关于UDP数据包大小的文章,但一直无法得出正确的结论。
许多服务将最大的UDP数据包限制在512字节(如dns)
假定internet上的最小MTU是576,IPv4报头的大小是20字节,UDP报头的大小是8字节。这就为用户数据留下了548个字节可用
我是否能够使用548大小的数据包而不产生数据包碎片?或者DNS的创造者知道一些事情,这就是为什么他们把它限制在512字节。
我能安全的把数据设置在548字节以上吗?
当前回答
根本没有。
我将完全撇开任何“UDP是最好的努力”的推理,只关注“最大安全UDP数据包大小”,这意味着“小到足以完全避免路径上的任何碎片”。
重要背景:
在没有分片的情况下,你唯一可以依赖的可传输的数据包大小是IPv4的24字节和IPv6的56字节,因为一个分片的最小IP头是20/48字节(v4/v6),并且一个分片必须至少有4/8字节(v4/v6)的有效载荷数据。因此,IP层以下的传输系统不能传输至少这些大小的数据包,不能用于传输IP流量。-回答“UDP中的MTU 65507如何?”
根据上面的答案,这是因为在这样的长度下,IP分片机制无法运行——它只能生成单个分片。
…IP标准要求每个IP主机能够接收总大小为576字节的IP数据包....然而,请注意,标准并没有说576没有分片,因此即使是576字节的IP数据包也可能在两台主机之间(源和目的地之间路径的某个位置)发现自己被分片了。
因此,任何比互联网协议可能做的最小值更大的东西,实际上可能会发现自己被“无形地”临时封装到路径上的某个地方,仅仅高于限制,即使你选择了最小的UDP有效载荷,这将是:576 - 8 (UDP报头)- 20 (IPv4)或40 (IPv6) = 528的min(以防你不确定是v4还是v6将被使用)。
您可能试图避免碎片化的一个原因是,它确实增加了数据包完整丢失的可能性。更多的数据包,仅仅是由于更高的开销,就意味着更大的失败可能性,更不用说每个数据包(甚至是一个片段)代表着另一个丢失的“机会”。当然,如果它碰巧被传递给某个链接,因为它太大而丢弃它……
操作系统级别的TCP实现尝试在TCP层中选择最高的安全MTU,包括有时动态地处理它,因为源和目的地之间的部分路径可能逐包不同。
对于UDP,这整个问题也变成了你的:它不是那么简单,只是“使用最大的,肯定不会碎片”。
RFC2460第5节是这么说的(关于IPv6的最小MTU)。
IPv6要求互联网上的每条链路都有1280的MTU 八位或更大。在任何不能传输1280字节的链路上 数据包在一块,链路特定的碎片和重组必须 在IPv6以下的层提供。
因此,碎片也可能发生在IP级别以下,在路径上的两个主机之间的特定链接决定将其碎片化,然后可能将碎片推到平行管道中……在这条链路的另一端把它们重新组装成一个数据包。
如果这些片段的顺序不正确,那么记录机制可能会错误地重新组装数据包,甚至没有意识到它重新排序了其中的一部分。
当然,如果硬件坚持IP规范,它应该能够通过检查IP报头的片段偏移部分来注意到数据包无序,但是大多数链路协议只是按照接收的顺序重新组装片段,而不担心无序的数据包接收。
现在,如果“较低水平”的互连本身被用作网络……例如,在一个大型开关的核心内部,那么在重载和许多并行路径下,这些碎片可能在重新组装之前就失去了秩序。
这是超级邪恶的,但可能有时确实会发生,导致偶尔仍然交付,但严重损坏的数据包,仍然通过简单的基于xor的校验和测试……也就是IP校验和。
TCP只是设置“不分片”并处理它,但UDP留下了清晰的bit…所以如果你使用UDP,你也应该假设你的字节流有时可能会被重新排序,甚至在数据包中…所以你应该使用校验和方法来验证你的数据,这个方法可以捕捉到重新排序。
大多数链路无论如何都会做1500 MTU,但链路层有不同的最小和最大数据报大小:
以太网:64到1500(或更高,具有更高的MTU能力) ATM: 53字节/数据报 帧中继:46 ~ 4470字节 (参考:IP碎片破碎
不幸的是,UDP头本身是8字节…所以这意味着,唯一能够避免碎片的UDP有效载荷…是零!(并且无论如何只适合最小的IPv6数据包)。
最好的/合理的方法可能是对UDP数据报使用512,并自己检查数据报中的数据是否无序,以及处理无序到达的数据包。(也就是说,完全不依赖IP为你丢弃坏掉的数据包)。
其他回答
UDP报文的最大大小的理论限制(Windows)是65507字节。这是记录在这里:
正确的UDP消息最大大小是65507,由以下公式确定: 0xffff -(sizeof(IP头)+ sizeof(UDP头))= 65535-(20+8)= 65507
也就是说,大多数协议限制的大小要小得多——通常是512或偶尔是8192。如果你在一个可靠的网络上,你通常可以安全地超过548,但如果你在整个互联网上广播,你的频率越大,你就越有可能遇到数据包传输问题和丢失。
本文介绍了最大传输单元(MTU) http://en.wikipedia.org/wiki/Maximum_transmission_unit。它规定IP主机必须能够处理576字节的IP数据包。然而,它指出,最低是68。RFC 791:“每个互联网模块必须能够转发一个68字节的数据报,而不会产生进一步的碎片。这是因为一个互联网报头可能高达60个字节,而最小的片段是8个字节。”
因此,安全数据包大小508 = 576 - 60 (IP头)- 8 (udp头)是合理的。
正如user607811所提到的,其他网络层的碎片必须重新组合。 https://www.rfc-editor.org/rfc/rfc1122#page-56 3.3.2重新组装 IP层必须实现IP数据报的重组。 我们指定可以重新组合的最大数据报大小 通过EMTU_R(“有效MTU接收”);有时候 称为“重组缓冲区大小”。EMTU_R必须更大 大于或等于576
UDP不是“安全的”,所以问题不是很大-然而-
如果你使用的是Mac,默认情况下你可以发送的最大大小是9216字节。 如果你在Linux (CentOS/RedHat)或Windows 7上,最大是65507字节。
如果你发送9217或更多(mac)或65508+ (linux/windows),套接字发送函数返回一个错误。
上面讨论碎片和MTU等问题的答案是跑题的——所有这些都发生在较低的级别,对你来说是“看不见的”,并且在很大程度上不会影响典型连接的“安全性”。
要回答实际的问题,不要使用UDP,使用原始套接字,这样你就可以更好地控制一切;因为你是在编写一款游戏,所以你需要深入研究标志以获得流量的优先级,所以你也可以同时摆脱UDP问题。
UDP最大安全负载是508字节。这是一个576(“最小最大重组缓冲区大小”)的数据包大小,减去最大60字节的IP头和8字节的UDP头。
任何这种大小或更小的UDP有效载荷都保证可以通过IP传递(尽管不保证传递)。任何更大的值都允许被任何路由器以任何理由直接丢弃。只有ipv6路由例外,ipv6路由最大负载为1212字节。正如其他人所提到的,在某些情况下可以添加额外的协议头。更保守的大约300-400字节的值可能是首选的。
最大可能的UDP负载是67 KB,分成45个IP包,增加额外的900字节开销(IPv4, MTU 1500,最小20字节IP头)。
任何UDP报文都可能被分片。但这并不太重要,因为丢失一个片段与丢失一个未分片的数据包具有相同的影响:整个数据包被丢弃。使用UDP,这将发生任何一种方式。
IP报文中包含一个分片偏移字段,表示UDP分片相对于其UDP报文的字节偏移量。该字段是13位的,允许8192个值,这些值以8字节为单位。所以IP包可以引用的偏移量范围是0…65528字节。作为偏移量,我们为最后一个UDP片段添加1480,得到67,008。减去第一个片段中的UDP头,我们得到了一个漂亮的约67 KB。
来源:RFC 791, RFC 1122, RFC 2460
512是您最好的选择。它在其他地方也被使用,是一个不错的偶数(1024的一半)。