目录分片与组装的过程分片1. 检查 MTU 限制2. 分割数据报3. 添加 IP 头部4. 发送分片组装1. 接收分片2. 排序与组装3. 传递给上层协议分片与组装过程的示意图分片组装场景分片组装过程1. 分片过程分片结果2. 组装过程接收方• 16 位标识(id): 唯一的标识主机发送的报文. 如果 IP 报文在数据链路层被分片 了, 那么每一个片里面的这个 id 都是相同的.• 3 位标志字段: 第一位保留(保留的意思是现在不用, 但是还没想好说不定以后要 用到). 第二位置为 1 表示禁止分片, 这时候如果报文长度超过 MTU, IP 模块就会丢 弃报文. 第三位表示更多分片, 如果分片了的话, 最后一个分片置为 0, 其他是 1. 类 似于一个结束标记.• 13 位分片偏移(framegament offset): 是分片相对于原始 IP 报文开始处的偏移. 其实就是在表示当前分片在原报文中处在哪个位置. 实际偏移的字节数是这个值 除 以 8 得到的. 因此, 除了最后一个报文之外(之前如果都是 8 的整数倍最后一片的 偏移量也一定是 8 的整数倍), 其他报文的长度必须是 8 的整数倍(否则报文就不连续 了).• 注意片偏移(13 位)表示本片数据在它所属的原始数据报数据区中的偏移量 以 8 字节为单位分片与组装的过程分片1. 检查 MTU 限制 当一个 IP 数据报的大小超过了网络的 MTU最大传输单元限制时就需 要进行分片。MTU 是数据链路层对 IP 层数据包进行封装时所能接受的最大数据 长度。2. 分割数据报 IP 层将原始的 IP 数据报分割成多个较小的片段。 对于每个片段IP 层会设置相应的标识Identification、偏移量 Fragment Offset和标志位Flags等字段。 标识字段用于标识属于同一个数据报的不同分片确保所有分片能够被正确 地重新组装。 偏移量字段指示了当前分片相对于原始数据报的起始位置以 8 字节为单 位。 标志位字段包含了 3 个位其中 MFMore Fragment位用于指示是否还 有更多的分片DFDo Not Fragment位用于指示数据报是否允许进行分片。3. 添加 IP 头部 每个分片都会加上自己的 IP 头部与完整 IP 报文拥有类似的 IP 头结构但 MF 和 Fragment Offset 等字段的值会有所不同。4. 发送分片 分片在传输过程中独立传输每个分片都有自己的 IP 头部并且各自独立 地选择路由。组装1. 接收分片 当目的主机的 IP 层接收到这些分片后会根据标识字段将属于同一个数据 报的所有分片挑选出来。2. 排序与组装 利用片偏移字段IP 层会对属于同一个数据报的分片进行排序。 当所有的分片都到达并正确排序后IP 层会将这些分片重新组装成一个完整 的 IP 数据报。3. 传递给上层协议 组装好的 IP 数据报会传递给上层的协议进行处理。注意• IP 分片对传输层是透明的这意味着传输层无需关心数据是否被分片以及如何 重新组装。• 接收方如何得知自己收到的报文分片了IP数据报头部中有三个关键字段帮助判断标志位Flags中的MFMore Fragments位若MF1表示当前分片之后还有更多分片。片偏移Fragment Offset字段若片偏移 0表示当前分片不是原始报文的第一个分片。总长度Total Length字段结合IP头部的“总长度”与“片偏移”也可间接判断。结论只要收到一个IP包满足MF1或者片偏移 0就说明它是一个分片且该报文被分片了。第一个分片片偏移0但MF1最后一个分片MF0但片偏移0中间的分片两者都满足• 接收方如何得知自己收到的分片收全了接收方对相同标识符Identification的所有分片进行重组判断是否收全的条件是收到了一个MF0的分片即最后一个分片并且该分片的片偏移 数据长度恰好等于从第一个分片推导出的原始数据报总长度或等于所有已收分片的数据总长度。在实际实现中重组过程会维护一个重组缓冲区持续接收同一标识符的分片。当遇到MF0的分片时检查它结束位置是否覆盖了所有数据范围。如果覆盖完整则重组成功否则可能丢失中间分片。另外IP协议还设计了重组超时定时器通常几十秒如果定时器到期仍未收齐全部分片则丢弃已收到的分片并向源端发送ICMP超时消息类型11代码1。• 接收方如何组合形成完整的报文组合过程如下以IPv4为例根据标识符Identification分类接收方从接收到的IP包中提取标识符字段将相同标识符的分片归到同一个重组任务。按片偏移排序每个分片的片偏移字段指示了该分片的数据在原始数据报中的起始位置以8字节为单位。接收方将这些分片按片偏移从小到大的顺序排列。拼接数据从第一个分片片偏移0开始依次取出每个分片的数据部分按照片偏移的顺序放入一个连续的缓冲区中。第一个分片可能但不必包含IP头部的选项但重组时只提取数据部分。后续分片只包含数据不包含原始IP头部。去除分片头部每个分片都有自己的IP头部20字节选项重组后的数据报只需要保留第一个分片的IP头部或重建一个简化的头部然后修改总长度、清除分片相关标志MF0片偏移0更新头部校验和。交付上层协议完整IP数据报重组后根据头部中的协议字段如6TCP17UDP交给相应的传输层模块处理。传输层完全感知不到曾经发生过IP分片。简化的例子假设一个1480字节的UDP报文数据部分1460字节UDP头8字节需要经过一个MTU1000的链路。原始IP数据报总长度 1480 20IP头 1500字节分片1IP头前980字节数据MF1片偏移0分片2IP头后500字节数据MF0片偏移980/8122.5不对片偏移单位是8字节980不是8的倍数实际IP分片要求每片数据长度是8字节的整数倍除了最后一片。这里为简化假设合理分片。接收方收到分片1MF1、分片2MF0片偏移122分片1数据长度960字节必须8倍数假设分片2数据长度500字节不足8倍数也可。计算分片2结束位置 片偏移×8 分片2数据长度 122×8 500 976 500 1476字节原始数据报总数据长度应为1476字节不含IP头。第一个分片偏移0数据960字节。检查960 500 1460不对需要精确对齐实际例子中会严格保证。关键是接收方通过排序和拼接就能恢复出原始数据。分片与组装过程的示意图分片组装场景分片组装过程• 假设在 IP 层有一个大小为 3000 字节的报文如何分片如何组装呢1. 分片过程每个分片包含自己的 IP 头部20 字节。每个分片携带的数据部分必须是8 字节的整数倍除了最后一个分片。每个分片的最大数据量 MTU - IP头部 1500 - 20 1480 字节正好是 8 的倍数。分片结果分片数据部分偏移原始数据中的起始字节数据长度IP 头部总长度MF 标志片偏移单位8 字节计算1014801500101480/818521480148015001185(14801480)/8370? 不对第二片的片偏移1480/818532960204003702960/8370说明原始数据总长 2980 字节。第一片携带数据 [0, 1479]共 1480 字节IP 报头总长度 1500MF1片偏移0。第二片携带数据 [1480, 2959]共 1480 字节IP 报头总长度 1500MF1片偏移185因为 1480 ÷ 8 185。第三片携带数据 [2960, 2979]共 20 字节IP 报头总长度 40MF0片偏移370因为 2960 ÷ 8 370。2. 组装过程接收方接收方可能收到乱序的分片例如顺序是分片2、分片1、分片3。步骤 1识别属于同一原始数据报的分片根据 IP 头中的源 IP、目的 IP、协议、标识符四个字段将分片归类。此处假设所有分片的标识符Identification相同如0x1234。步骤 2按片偏移排序收到的分片信息分片片偏移MF数据长度21851148010114803370020排序后分片片偏移MF数据长度起始字节结束字节不含10114800148021851148014802960337002029602980步骤 3检查是否收全最后一个分片的 MF0其结束位置 片偏移 × 8 数据长度 370×8 20 2960 20 2980 字节。这正好等于原始数据总长度所有分片数据之和。收全条件满足。步骤 4重组数据创建一个 2980 字节的缓冲区按顺序复制复制分片1 的数据1480 字节到缓冲区 [0, 1479]。复制分片2 的数据1480 字节到缓冲区 [1480, 2959]。复制分片3 的数据20 字节 到缓冲区 [2960, 2979]。步骤 5构建完整的 IP 数据报取出第一个分片的 IP 头部或重建一个将其中的总长度修改为 300020 头部 2980 数据。清除分片标志MF0片偏移0。重新计算 IP 头部校验和。将重组后的数据附加到头部后面。这样就得到了一个完整的 3000 字节 IP 数据报可以交付给上层协议如 TCP/UDP。注意如果某个分片丢失例如一直没收到 MF0 的分片接收方会启动一个重组超时定时器典型值 30 秒。超时后丢弃已收到的分片并可能发送ICMP 超时消息类型 11代码 1。传输层TCP/UDP完全感知不到分片的存在 —— 它们收到的就是已经组装好的完整报文。