Maximum Segement Size (MSS) 最大分段长度
tcp会将应用层交付下来的数据分为tcp认为最适合发送的数据块(这里的最适合指的是用户可以自己配置mss长度),单位为字节,发送端的传输层进行数据分块,这些数据块的大小就是mss,在接受端端传输层对分块的tcp报文段的数据部分进行重组。注意,mss不包含tcp首部的20字节,只是数据块长度。
如果tcp接收到的数据包超过mss就会进行分段。
Maximum Transmission Unit (MTU) 最大传输单元
数据链路层所能传输的最大数据包大小,单位为字节,大小由具体的网络来定。一般情况下,以太网的 MTU=1500字节。
ip所在的网络层是离数据链路层较近的,所以如果ip接收到的传输层的数据包超过MTU就会进行分片,分片的行为传输层是不知道的。
如果传输层使用tcp会引起分片吗?使用udp会引起分片吗?
- tcp可以避免ip分片,因为tcp会主动分成刚好放进MTU的MSS大小的段交付给网络层。最大的MSS相当于MTU刨去IP首部和TCP首部之后的长度,所以一个MSS刚好可以放进MTU中。
- 而udp是没有主动分段的行为的,udp会直接将应用层的数据包交付给网络层,因此很可能会被ip进行分片。
分片和重组都会影响数据包传输的效率,所以能够尽量避免肯定是最好的。
那么发送端和接受端是如何确定对方的MSS?
- 首先客户端会发送一个SYN请求报文,这个SYN报文的"选项"字段中会有MSS值(MSS是计算过了的,MSS=MUT-IP首部长度-TCP首部长度),告知对方自己最大能发送的数据大小。
- 当服务端收到带MSS的SYN报文后,就可以确定当前对话所使用的MSS值了,也就是从自己的MSS和客户端的MSS中选一个最小的。然后服务端会向客户端发送SYN+ACK的同步确认报文,报文中的"选项"字段也会有MSS值,告知客户端自己能够发送的最大数据包长度。
- 客户端收到服务端带有服务端MSS的同步确认报文后,就可以确定和服务端对话使用的MSS了,也就是从自己的MSS和服务端MSS选取一个最小的。然后客户端向服务端发送ACK报文。
- 服务端接收到客户端的ACK报文,完成三次握手。
因此,在tcp三次握手过程中的第二次握手可以确定MSS。
tcp真的可以彻底避免分片吗?
不能。
因为在根本上,MTU是受到了数据链路层的限制,报文传输的路径上经常会有MTU值小于该TCP连接协商得到的MTU值的链路,在转发至该段链路之前转发设备仍需分片,所以说TCP分段并不能完全避免IP分片。
那么如何彻底避免分片?
参考:TCP分段与IP分片的区别与联系 - 云+社区 - 腾讯云
答案其实不难想到:如果能在TCP连接双方正式通信之前,就能通过某种方式预先知道端到端路径的MTU,即路径中包含的各条链路的MTU最小值(称为路径MTU,Path MTU),这一预先获知路径MTU的过程,称为路径MTU发现(Path MTU Discovery),这样此后每次通信都会基于此MTU推导得到的MSS值在发送方TCP层处执行分段。
路径MTU发现如何实现呢?
大家都记得IP首部中有三个标志位,第一位预留,第二位DF(Don't Fragment),第三位MF(More Fragments)。其中DF如果为1,意思是这个IP数据报在传输的过程中不能分片,如果此IP数据报大于网络接口的MTU,请直接丢弃,并发送消息告诉源主机已丢包。
什么消息呢?ICMP的消息,告诉包因为太大了,因为不能分片所以丢弃了,并告诉源主机请重新发送不超过MTU的数据报,那发什么样的ICMP消息呢?再回顾一下ICMP首部结构,有一个Type字段,还有Code字段,发送Type=3, Code=4, MTU=该接口的MTU值X的消息既可以了。当这个ICMP消息到达IP数据报的源主机,源主机知道原来是IP数据报太大了,那最大可以发送多大的包呢?ICMP消息里有,那就是MTU=丢弃该包的网络接口的MTU值X,于是源主机再次发送不超过MTU=X的数据报就可以避免在传输路径上的IP分片。
有人会说,如果这个大小不超过X的IP数据报在传输过程中又遇到更小的MTU怎么办?重复以上步骤即可~
路径MTU发现看似完美避免了IP分片的问题,但同时又带来了新的问题:如果ICMP消息最终没能到达源主机怎么办?很显然该IP数据报就被静静丢弃了,TCP连接超时而被断开。ICMP为什么回不来?一般是被防火墙或路由器的访问控制列表(Access Control List, ACL)给无情拒绝了。如果你可以管理并配置这些设备,只要允许ICMP Type=3, Code=4 的消息可以通过即可,否则只有老老实实关闭路径MTU发现功能了,因为至少分片还能通信,而避免分片则彻底无法通信了…
总结:
- 分段和分片行为发生在不同的协议层,分段是在传输层,由tcp规定,分片是在网络层,是被数据链路层限制,由ip协议规定。
- 传输层的协议不同会发生不同的划分行为,比如tcp分段不分片,udp和icmp等由于不分段会引起分片。
- 分段仅仅会发生在发送端,但是分片不仅可能发生在发送端,也有可能发生在路径上任何工作在三层或以上的设备中,但分段和分片引起的数据包重组只会发生在接收端。