- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
哈喽大家好,我是咸鱼 。
在 《计算机网络那些事之 MTU 篇 》 中,咸鱼跟大家介绍了 MTU 是指数据链路层能够传输的最大数据帧的大小 。
如果发送的数据大于 MTU,则就会进行分片操作(Fragment);如果小于 MTU,就会在实际数据内容后面添加填充数据(Padding),使得数据包总长度达到最小长度要求 。
TCP 因为是有连接的协议,连接在建立的时候就有 MSS(TCP 报文段中数据部分的最大长度) 的协商,以便在传输过程中进行分片 。
在网络传输的过程中,如果中间设备(例如路由器)的 MTU 比较小,就会 MSS clamping 。
MSS clamping 是一种 TCP 优化技术,用于解决 TCP 数据包在传输过程中可能发生的分片问题 。
它会检查 TCP SYN 包中的 MSS 选项,并将其值与网络链路的 MTU 进行比较 。
如果 MSS 值大于 MTU,就将 MSS 值设置为 MTU 减去 IP 头部和 TCP 头部的长度,从而保证 TCP 数据包的大小不会超过网络链路的 MTU,避免发生 IP 分片 。
在 TCP 连接建立后,双方会根据 MSS 值来控制每个 TCP 数据包的大小,从而保证 TCP 数据包不会超过网络链路的 MTU,提高网络传输的效率 。
但是对于面向无连接的协议(例如 UDP ),这时候该怎么办呢?
我们知道以太网规定 MTU 范围上限为 1500 字节,那么 理论上 UDP 能传输的数据包大小上限为:
MTU(1500) - IP Header(20) - UDP Header(8) = 1472 字节 。
但我们需要知道的是, UDP 包进行分片的时候不像 TCP 那样每个分片里面都复制一个 Header 。
而是第一个分片有 UDP Header,其余的都没有 。
所以接收方拿到 UDP 分片包之后在传输层就得先进行重组成一个完整的 UDP 包然后才能交给上一层 。
这样就会导致一个问题:如果在传输过程中其中一个 UDP 分片包丢了,造成 UDP 包重组失败,接收方会把整个包给丢掉 。
但是又因为 UDP 没有重传机制,就会导致 UDP 发送方不知道接收方丢了这个包 。
然后发送方就会一直发包,接收方一直丢包 。
所以说最好不要发超过接收方 MTU 大小的 UDP 数据包 。
但面向无连接的 UDP 是怎么知道对方 MTU 的呢?(TCP 有 MSS 协商) 。
为此我在虚拟机上简单做了一个实验 。
然后用 B 服务器去 ping 服务器 A,发送一个大小为 1500 bytes 的数据 。
# -M do 表示不分片
# -p 选项用于指定数据包的内容
# -c 2 指定发送数据包的数量为2
# -s 指定数据包的大小
ping -c 2 -s 1000 -M do -p $(echo -n abcdefghijklmnopqrstuvwxyz | xxd -p) 192.168.149.130
结果发现服务器 A 全部接受了,按理说 A 的 MTU 是 800,又因为设置了不分片,应该丢弃这个包才对 。
然后我们用 B 服务器去 ping 服务器 A,发送一个大小为 1600 bytes 的数据 。
发现超出服务器 B 的 MTU (1500)了,又因为不允许分片,导致包不能发出 。
ping -c 2 -s 1600 -M do -p $(echo -n abcdefghijklmnopqrstuvwxyz | xxd -p) 192.168.149.130
跟我想象的不太一样,服务器 A 收到服务器 B 发送的超过自身 MTU 大小的包应该是丢弃,然后回复一个:
Type=3 (Destination Unreachable) and code=4, packet too big and DF is set
表示发送方数据包无法到达目的地且无法分片 。
后面我查了一下,应该是本地环境即两个虚拟机之间的网络比较简单,导致网卡能接受这种不合理的包,如果有懂的小伙伴可以私信我 。
但是这个实验至少证明了一点:即 服务器不会去关心对方的 MTU,只会根据自己的 MTU 去进行分片 。
然后我又查阅了大量的资料,我看到一个比较贴切的答案就是:
我们来看下上面这段内容,可以得出 。
在 RFC 中, Internet (IPv4) 标准规定 MTU 最小是 576 bytes 。
所以对于 UDP 来讲,能发的有效数据(Payload)只要不超过 508 bytes 。
576 bytes (MTU) - 60 bytes (IP header 20 bytes + IP option 0-40 bytes) - 8 bytes (UDP Header)= 508 bytes 。
我管你服务器的 MTU 是多少,我只发送全世界最小的二层包,总没问题了吧?
很多情况下 IP header 是达不到 60 bytes的,所以一般 UDP 的 Payload 也会是是 512 bytes 。
总结一下:
Beej's Guide to Network Concepts 。
domain name system - Why DNS through UDP has a 512 bytes limit? - Server Fault 。
MTU 和 UDP (以及基于 UDP 的协议) | 卡瓦邦噶! (kawabangga.com) 。
最后此篇关于计算机网络那些事之MTU篇pt.2的文章就讲到这里了,如果你想了解更多关于计算机网络那些事之MTU篇pt.2的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我是一名优秀的程序员,十分优秀!