【TCP】为什么MSS都小于MTU?

MTU: Maximum Transmit Unit,最大传输单元,即物理接口(数据链路层)提供给其上层(通常是IP层)最大一次传输数据的大小;以普遍使用的以太网接口为例,缺省MTU=1500 Byte,这是以太网接口对IP层的约束,如果IP层有<=1500 byte 需要发送,只需要一个IP包就可以完成发送任务;如果IP层有> 1500 byte 数据需要发送,需要分片才能完成发送,这些分片有一个共同点,即IP Header ID相同。

MSS:Maximum Segment Size ,TCP提交给IP层最大分段大小,不包含TCP Header和 TCP Option,只包含TCP Payload ,MSS是TCP用来限制application层最大的发送字节数。如果底层物理接口MTU= 1500 byte,则 MSS = 1500- 20(IP Header) -20 (TCP Header) = 1460 byte,如果application 有2000 byte发送,需要两个segment才可以完成发送,第一个TCP segment = 1460,第二个TCP segment = 540。

image.png
# ip addr list
image.png
image.png

MTU一经确定不再改变?

实际上MTU并不是确定了之后就一直不变的,每个端上查看到的MTU并非是最终的MTU大小,这个怎么理解呢?

大部情况下,网络发送端都需要经过各种中间设备才能到达目标机器,这些中间设备可能是路由器、交换机、中间代理服务器等等,这些设备的MTU大小可能有大有小,更糟糕的是,每次走的路径不一样MTU大小可能也不一样。那么,假如我们的发送端的MTU是1500,中间某个交换机或者路由器的MTU是200字节,当数据包到达这个设备的时候IP层就会触发拆包,我们上面详细分析了IP层拆包存在的问题。所以,很明显如果出现这种情况网络传输效率会大幅降低。那么有什么办法可以解决这个问题呢?

我们可以思考一下,要解决这个问题其实只要找到链路中最小的MTU就可以了,那么,我们如何感知中间设备的MTU呢?有一个叫ICMP的协议可以在中间设备出现异常的时候将异常返回,从而发送端可以感知到,关于ICMP协议这里不展开,有兴趣可以自行去了解。

# ping -s 1700 -M do www.seepre.com
PING www.seepre.com (106.12.210.214) 1700(1728) bytes of data.
ping: local error: message too long, mtu=1500
ping: local error: message too long, mtu=1500
ping: local error: message too long, mtu=1500

-s表示发送多少字节,ping会填充对应的字节数将包发出去
-M表示回显MTU相关的错误信息
最终我们看到返回了错误,提示说我们发送的数据超长了,并且提示当前链路中MTU的大小。

这样的话,我们就可以拿到整个链路中最小的那MTU了,传输层便可以根据最小的MTU来设置自己的MSS,比如,前面的例子,假如中间某个设备的MTU仅为200字节,那MSS就设置成160字节,这样TCP每次发送的数据包就不会超过200字节,也就不会触发IP层的拆包了。

实际上,TCP协议已经实现了链路MTU的探测,叫做PMTU,原理就是设置IP报头DF不分片位置为不分片,这样当遇到比MSS小的MTU的设备,这个设备就会返回一个ICMP报文,里面携带了错误消息和可接受的MTU大小。

image.png

参考

1500字节为何成为互联网MTU标准?
https://www.freesion.com/article/5773577654/

Path MTU 概述
http://sunyongfeng.com/201712/networks/path_mtu

为什么MSS都小于MTU?
https://blog.csdn.net/mrosrry/article/details/125162204

什么是MTU(Maximum Transmission Unit)?
https://info.support.huawei.com/info-finder/encyclopedia/zh/MTU.html

如何利用ping命令拥有最佳MTU?
https://blog.csdn.net/weixin_34112181/article/details/85195009

你可能感兴趣的:(【TCP】为什么MSS都小于MTU?)