我读过许多关于UDP数据包大小的文章,但一直无法得出正确的结论。

许多服务将最大的UDP数据包限制在512字节(如dns)

假定internet上的最小MTU是576,IPv4报头的大小是20字节,UDP报头的大小是8字节。这就为用户数据留下了548个字节可用

我是否能够使用548大小的数据包而不产生数据包碎片?或者DNS的创造者知道一些事情,这就是为什么他们把它限制在512字节。

我能安全的把数据设置在548字节以上吗?


当前回答

我担心我会引起不安的反应,但尽管如此,为了澄清我是否错了,或者那些看到这个问题并对答案感兴趣的人:

我对https://www.rfc-editor.org/rfc/rfc1122的理解,它的状态是“官方规范”,因此是这个问题中使用的术语的参考,它既没有被另一个RFC取代,也没有与以下内容相矛盾的错误:

从理论上讲,ie。根据书面规范,像https://www.rfc-editor.org/rfc/rfc1122#section-4这样的UDP没有“数据包大小”。因此答案可能是“不确定的”

在实践中,这就是这个问题可能寻求的(以及可以根据当前的技术进行更新),这可能是不同的,我不知道。

如果我造成了困扰,我道歉。https://www.rfc-editor.org/rfc/rfc1122#page-8“互联网协议套件”和“架构假设”并没有让我清楚地知道我所做的“假设”,基于我所听到的,这些层是分开的。Ie。UDP所在的层不需要关心IP所在的层(IP层确实有像重组,EMTU_R,碎片和MMS_R (https://www.rfc-editor.org/rfc/rfc1122#page-56))

其他回答

IPv4最小重组缓冲区大小为576,IPv6为1500。从这里减去标题大小。参见W. Richard Stevens的UNIX网络编程:)

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

本文介绍了最大传输单元(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

考虑到IPV6的大小为1500,我认为运营商不会为IPV4和IPV6提供单独的路径(它们都是不同类型的IP),迫使它们使用旧的、冗余的、维护成本更高、可靠性更低的IPV4设备。这没有任何意义。此外,这样做可能很容易被认为是为某些流量提供优惠待遇——在他们可能不太关心的规则下(除非他们被抓住),这是不允许的。

因此,1472对于外部使用应该是安全的(尽管这并不意味着像DNS这样的应用程序不知道EDNS将接受它),如果你谈论的是内部网络,你更可能知道你的网络布局,在这种情况下,巨型数据包大小适用于非碎片数据包,因此对于4096 - 4068字节,对于英特尔卡的9014字节缓冲区,包大小为…… 等待……8086字节,是最大的…巧合吗?窃笑

* * * * * * * *更新

各种答案给出软件供应商允许的最大值或假设封装的各种答案。用户并没有要求尽可能低的值(比如安全的UDP大小为“0”),而是要求最大的安全数据包大小。

各个层的封装值可以被多次包含。因为一旦封装了一个流,就没有什么可以禁止的了,比如说,在它下面有一个VPN层,在它上面有一个完全复制的封装层。

由于这个问题是关于最大安全值的,我假设他们谈论的是可以接收的UDP数据包的最大安全值。由于没有UDP数据包是保证的,如果你收到一个UDP数据包,最大的安全大小将是IPv4上的1个数据包或1472字节。

注意——如果你使用IPv6,最大大小将是1452字节,因为IPv6的报头大小是40字节,IPv4是20字节(无论哪种方式,仍然必须允许8字节的UDP报头)。