【UDP】——为什么 UDP 数据包不能超过 512 个字节

简介: 一开始了解的是 DNS 服务使用的是 UDP 协议,后面看到 DNS 服务主要使用 UDP 协议,在少数情况(传输的数据超过 512 个字节)下也会使用 TCP 协议,因为 UDP 数据包不能超过 512 个字节。那问题来了,为什么 UDP 数据包不能超过 512 个字节呢?

问题

      一开始了解的是 DNS 服务使用的是 UDP 协议,后面看到 DNS 服务主要使用 UDP 协议,在少数情况(传输的数据超过 512 个字节)下也会使用 TCP 协议,因为 UDP 数据包不能超过 512 个字节。


那问题来了,为什么 UDP 数据包不能超过 512 个字节呢?


探索

    首先,对于传输层,即 UDP 数据包本身来说,Length 字段为 16 位,理论限制为 65535 字节(2^16 - 1),那么能传输的数据为 65535 - IPHeader(20) - UDPHeader(8) = 65507 字节。

其次,对于网络层,以太网规定 MTU 上限为 1500 字节(综合权衡的结果),如果按照 MTU = 1500 计算,那么 UDP 能传输的数据包上限为 MTU(1500) - IPHeader(20) - UDPHeader(8) = 1472 字节。

  • 如果 UDP 数据包小于等于1472 个字节,那么正常发送不用分片
  • 如果 UDP 数据包超过 1472 个字节,那么移交网络层进行分片并在接收方进行重组

这里补充一下 UDP 超过 1472 字节时的切片处理

网络层并不会在每个分片里复制一次 UDP 头,它是把完整的 UDP 包切开,加上 IP 头发送出去,除了第一个分片有 UDP 头,后面的分片都不包含 UDP 头。

目的主机的网络层接收到多个 UDP 分片包后,网络层必须重组才能交给上层。因为多个分片包只有第一个是有 UDP 头的,它可以根据 UDP 头里的端口号通知相应的应用取走,但是后面的分片包由于没有 UDP 头,传输层无法把分片包交给正确的应用程序。所以 UDP 分片包必须在网络层重组成一个完整的 UDP 包,再交给传输层处理,耗费资源。

但如果某些分片包没有被目的主机的网络层接收到,造成 UDP 包重组失败,接收方会丢弃整个数据包,这是 UDP 不可靠传输的一个表现。而 TCP 发 生组包错误时,该包会被重传,保证可靠传输。

 因此一般建议将 UDP 数据包限制在 1472 字节以下。但是呢,这个限制是在普通局域网(Ethernet v2)环境下的,在非局域网(X.25)环境下则有所不同

因为 Internet 上的路由器可能会将 MTU 设为不同的值。如果我们假定 MTU 为 1500 字节来发送数据的,而途经的某个网络的 MTU 值小于 1500 字节,那么系统将会使用一系列的机制来调整 MTU 值,使数据报能够顺利到达目的地,这样就会做许多不必要的操作。

鉴于 Internet 上的标准 MTU 值为 576 字节(IPv4 标准规定,每个主机必须能够重新组装 576 字节或更少的数据包),所以建议在进行 Internet 的 UDP 编程时,最好将 UDP 的数据长度控件在 548 字节(MTU(576) - IPHeader(20) - UDPHeader(8))以内。

但这也还是 548 字节,并不是 512 字节。于是又搜索了一番,发现 StackOverflow 上有一个回答提到:

典型的 IPv4 头部是 20 字节,而 UDP 头部是 8 字节。然而,可以包括 IP 选项,该选项可以将 IP头部的大小增加到多达 60 字节(如图 1 所示)。

此外,有时中间节点需要将数据报封装在另一种协议(如IPsec(用于VPN等))中,以便将数据包路由到其目的地。

因此,如果不知道特定网络路径上的 MTU,最好为可能没有预料到的其他头部信息留出合理的余量。512字节的 UDP 有效载荷通常被认为可以做到这一点,尽管即使这样也没有为最大尺寸的 IP报头留下足够的空间。

42ba9f6debbfc421d071a7575a3399e.png

图1,IPV4 头部字段,来源:Chapter 5. The Internet Protocol (IP) - Shichao's Notes

通过这个回答我们可以知道,UDP 数据包的最大安全负载应该是 508 字节(MTU(576) - IPHeader(60) - UDPHeader(8)),因为 IP 头部最大时为 60 字节。512 也是一个综合考虑的结果。


总结

     总的来说,这些数值的限制就是各层之间综合权衡的结果,以在整体上达到最优传输效率。当然,还得提一下,上述讨论针对的是 IPV4,而非 IPV6。

目录
相关文章
|
6天前
|
网络协议 iOS开发 MacOS
LabVIEW在快速传输速率下丢失UDP数据包
LabVIEW在快速传输速率下丢失UDP数据包
11 0
|
9月前
|
网络架构
为什么udp流设置1316字节
为什么udp流设置1316字节
56 0
|
5月前
|
存储 网络协议 Serverless
C/C++ 运用Npcap发送UDP数据包
Npcap 是一个功能强大的开源网络抓包库,它是 WinPcap 的一个分支,并提供了一些增强和改进。特别适用于在 Windows 环境下进行网络流量捕获和分析。除了支持通常的网络抓包功能外,Npcap 还提供了对数据包的拼合与构造,使其成为实现 UDP 数据包发包的理想选择。本章将通过Npcap库构造一个UDP原始数据包,并实现对特定主机的发包功能,通过本章的学习读者可以掌握如何使用Npcap库伪造特定的数据包格式。
121 0
C/C++ 运用Npcap发送UDP数据包
|
缓存 网络协议 算法
【web】TCP/UDP协议详解(字节二面:TCP三次握手、四次挥手)
本文介绍了计算机网络UDP/TCP协议格式和特点、重点介绍保证TCP可靠性的 确认应答机制(数据编码+超时重传)、连接管理机制(TCP三次握手、四次挥手)、流量控制机制、拥塞控制机制、快重传、延时应答、捎带应答机制等。
126 0
|
存储 网络协议 安全
IPsec ESP 数据包的 UDP 封装
选择共享 IKE 和 UDP 封装的 ESP 流量的端口号是因为它提供了更好的扩展性(NAT 中只有一个 NAT 映射;无需发送单独的 IKE keepalive)、更容易配置(仅在防火墙中配置一个端口),更容易实现。
1030 0
IPsec ESP 数据包的 UDP 封装
|
Java 数据处理
【Java 网络编程】UDP 服务器 客户端 通信 ( DatagramSocket | DatagramPacket | UDP 发送数据包 | UDP 接收数据包 | 端口号分配使用机制 )
【Java 网络编程】UDP 服务器 客户端 通信 ( DatagramSocket | DatagramPacket | UDP 发送数据包 | UDP 接收数据包 | 端口号分配使用机制 )
432 0
【Java 网络编程】UDP 服务器 客户端 通信 ( DatagramSocket | DatagramPacket | UDP 发送数据包 | UDP 接收数据包 | 端口号分配使用机制 )
|
网络协议 网络性能优化 安全
用户数据包协议(user datagram protocol)——UDP
用户数据报协议(User Datagram Protocol,UDP)是无连接不可靠传输层协议。它不提供主机到主机通信,它除了提供进程到进程之间的通信之外,就没有给 IP 服务增加任何东西。
1516 0
|
Python
python伪造udp数据包
#!/usr/bin/python #coding:utf-8 import socket import struct from random import randint def checksum(data): ...
2269 0