为什么要分片?
想象一下,你要给远方的朋友寄一套3000页的百科全书 (这就是一个大的IP数据报)。
但是,快递公司(数据链路层 )有一个死规定:每个包裹最多只能装1500页 (这就是MTU,最大传输单元,通常以太网MTU=1500字节)。
这时候你怎么办?你不能把书硬塞进去,只能拆开:
-
分片:把3000页的书拆成几个小包裹。
-
贴标签:每个包裹上都要写上"这是第几页到第几页"、"有没有漏掉"、"是不是最后一部分"。
-
运输:每个小包裹独立发货(IP分片各自独立路由)。
-
组装:朋友收到所有包裹后,按照标签重新排好顺序,装订成一本完整的书。
在计算机网络中,**IP层(网络层)**负责这个"拆包"和"贴标签"的工作。
核心概念:IP头部中的"三剑客"
要搞懂分片,你必须认准IP头部(IPv4)里的这三个关键字段:
1. 标识(Identification,16位)
-
作用 :"身份证号"。
-
解释:如果多个分片属于同一个原始报文,它们的标识字段必须完全一样。接收方就是靠这个ID把属于同一本书的碎片找出来的。
2. 标志(Flags,3位)
这是三个比特位,重点看后两个:
-
DF(Don't Fragment,第2位) :"禁止分片"。如果设为1,表示"宁可丢包,也不准拆我!"。如果网络MTU太小装不下,IP层直接丢包并报错(通常用于探测路径MTU)。
-
MF(More Fragment,第3位) :"还有更多"。
-
如果设为1:表示"我还没结束,后面还有分片"。
-
如果设为0:表示"我是最后一个分片啦!"(相当于结束标记)。
-
3. 片偏移(Fragment Offset,13位)
-
作用 :"页码"。表示当前分片的数据在原始报文数据中的位置。
-
关键单位 :注意!这个值是以"8字节"为单位的。
-
公式 :
实际字节偏移量 = 片偏移值 × 8。 -
为什么要除以8? 因为13位最大只能表示8191。如果不除以8,最大只能偏移8191字节,对于大报文不够用。除以8后,最大可以表示 8191×8≈655358191×8≈65535 字节,刚好覆盖IP报文的最大长度。
分片与组装的全过程
1. 分片过程(发送端)
当IP层发现数据包大小 > MTU时:
-
切数据:将数据部分切分。
-
算长度 :除了最后一片,前面的所有分片的数据部分长度必须是8的整数倍(因为片偏移字段是以8为单位计算的,如果长度不是8的倍数,偏移量就会除不尽,无法表示)。
-
填头部:每个分片复制原始IP头,修改总长度、标志位(MF)和片偏移(Offset)。
2. 组装过程(接收端)
-
收件 :收到一堆分片,先看标识(ID),把ID相同的分片归类。
-
排序 :看片偏移(Offset),按顺序排好。
-
查漏 :看MF标志。
-
如果MF=0的片还没到,说明还没收全。
-
如果MF=0的片到了,且前面的偏移量都连续(比如收到了0, 1480, 2960),说明收全了。
-
-
合并:把数据拼接起来,去掉所有分片的IP头(保留第一个原始头),传给上层(TCP/UDP)。
核心提示 :IP分片对传输层(TCP/UDP)是完全透明的。TCP根本不知道IP层把数据切碎了,它只负责收发完整的数据段。
扩展与深度思考
1. 接收方如何得知自己收到的报文分片了?
-
看MF标志:如果MF=1,或者MF=0但片偏移>0,那肯定是分片了。
-
看偏移量:如果偏移量不是0,说明它不是第一个。
2. 接收方如何得知分片收全了?
-
标志位法 :收到MF=0 的分片(最后一片),并且根据它的片偏移 和长度,算出原始报文的总长度。然后检查自己是否拥有了从0到总长度的所有字节片段。
-
定时器法:如果某个分片迟迟不到,接收方会启动一个定时器,超时后丢弃所有已收到的分片(防止内存耗尽)。
3. 如果任何一个分片丢失了怎么办?
-
全丢 !如果第2片丢了,接收方只有1和3,拼不起来。IP层会丢弃所有分片。**上层(TCP)**会因为超时重传整个原始报文(TCP是面向连接的,会重传)。
-
这也是为什么说IP分片是不可靠的,且应该尽量避免。UDP如果分片丢失,整个报文就废了。
4. 为什么TCP层要避免IP分片?
-
IP分片增加了丢包概率:因为只要任何一片丢了,整个报文都要重传。
-
TCP的MSS协商 :TCP通常会在三次握手时,根据MTU协商一个MSS(最大报文段长度) ,保证每个TCP段加上IP头后不超过MTU,从而在TCP层就切好,避免IP层再去分片。
-
MTU发现:现代操作系统会设置DF位,探测路径上的最小MTU,从而调整发送大小。