8-1\IP 分片和组装的具体过程

目录

分片与组装的过程

分片

[1. 检查 MTU 限制:](#1. 检查 MTU 限制:)

[2. 分割数据报:](#2. 分割数据报:)

[3. 添加 IP 头部:](#3. 添加 IP 头部:)

[4. 发送分片:](#4. 发送分片:)

组装

[1. 接收分片:](#1. 接收分片:)

[2. 排序与组装:](#2. 排序与组装:)

[3. 传递给上层协议:](#3. 传递给上层协议:)

分片与组装过程的示意图

分片组装场景

分片组装过程

[1. 分片过程](#1. 分片过程)

分片结果:

[2. 组装过程(接收方)](#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 个位,其中 MF(More Fragment)位用于指示是否还 有更多的分片,DF(Do Not Fragment)位用于指示数据报是否允许进行分片。

3. 添加 IP 头部:

○ 每个分片都会加上自己的 IP 头部,与完整 IP 报文拥有类似的 IP 头结构,但 MF 和 Fragment Offset 等字段的值会有所不同。

4. 发送分片:

○ 分片在传输过程中独立传输,每个分片都有自己的 IP 头部,并且各自独立 地选择路由。

组装

1. 接收分片:

○ 当目的主机的 IP 层接收到这些分片后,会根据标识字段将属于同一个数据 报的所有分片挑选出来。

2. 排序与组装:

○ 利用片偏移字段,IP 层会对属于同一个数据报的分片进行排序。

○ 当所有的分片都到达并正确排序后,IP 层会将这些分片重新组装成一个完整 的 IP 数据报。

3. 传递给上层协议:

○ 组装好的 IP 数据报会传递给上层的协议进行处理。

注意:

• IP 分片对传输层是透明的,这意味着传输层无需关心数据是否被分片以及如何 重新组装。

• 接收方如何得知自己收到的报文分片了?

IP数据报头部中有三个关键字段帮助判断:

  • 标志位(Flags)中的MF(More Fragments)位

    MF=1,表示当前分片之后还有更多分片。

  • 片偏移(Fragment Offset)字段

    片偏移 > 0,表示当前分片不是原始报文的第一个分片。

  • 总长度(Total Length)字段

    结合IP头部的"总长度"与"片偏移",也可间接判断。

结论 :只要收到一个IP包满足 MF=1 或者 片偏移 > 0,就说明它是一个分片(且该报文被分片了)。(第一个分片 片偏移=0MF=1;最后一个分片 MF=0片偏移>0;中间的分片两者都满足)

• 接收方如何得知自己收到的分片收全了?

接收方对**相同标识符(Identification)**的所有分片进行重组,判断是否收全的条件是:

  • 收到了一个 MF=0 的分片(即最后一个分片);

  • 并且该分片的片偏移 + 数据长度,恰好等于从第一个分片推导出的原始数据报总长度(或等于所有已收分片的数据总长度)。

在实际实现中,重组过程会维护一个重组缓冲区 ,持续接收同一标识符的分片。当遇到 MF=0 的分片时,检查它结束位置是否覆盖了所有数据范围。如果覆盖完整,则重组成功;否则,可能丢失中间分片。

另外,IP协议还设计了重组超时定时器(通常几十秒):如果定时器到期仍未收齐全部分片,则丢弃已收到的分片,并向源端发送ICMP超时消息(类型11,代码1)。

• 接收方如何组合形成完整的报文?

组合过程如下(以IPv4为例):

  1. 根据标识符(Identification)分类

    接收方从接收到的IP包中提取 标识符 字段,将相同标识符的分片归到同一个重组任务。

  2. 按片偏移排序

    每个分片的 片偏移 字段指示了该分片的数据在原始数据报中的起始位置(以8字节为单位)。接收方将这些分片按 片偏移 从小到大的顺序排列。

  3. 拼接数据

    从第一个分片(片偏移=0)开始,依次取出每个分片的数据部分,按照片偏移的顺序放入一个连续的缓冲区中。

    • 第一个分片可能(但不必)包含IP头部的选项,但重组时只提取数据部分。

    • 后续分片只包含数据,不包含原始IP头部。

  4. 去除分片头部

    每个分片都有自己的IP头部(20字节+选项),重组后的数据报只需要保留第一个分片的IP头部(或重建一个简化的头部),然后修改 总长度、清除分片相关标志(MF=0,片偏移=0),更新 头部校验和

  5. 交付上层协议

    完整IP数据报重组后,根据头部中的协议字段(如6=TCP,17=UDP),交给相应的传输层模块处理。传输层完全感知不到曾经发生过IP分片。

简化的例子

假设一个1480字节的UDP报文(数据部分1460字节+UDP头8字节)需要经过一个MTU=1000的链路。

  • 原始IP数据报总长度 = 1480 + 20(IP头)= 1500字节

  • 分片1:IP头+前980字节数据,MF=1,片偏移=0

  • 分片2:IP头+后500字节数据,MF=0,片偏移=980/8=122.5?不对,片偏移单位是8字节,980不是8的倍数?实际IP分片要求每片数据长度是8字节的整数倍(除了最后一片)。这里为简化,假设合理分片。

接收方收到分片1(MF=1)、分片2(MF=0,片偏移=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 字节) 计算
1 0 1480 1500 1 0 1480/8=185
2 1480 1480 1500 1 185 (1480+1480)/8=370? 不对,第二片的片偏移=1480/8=185
3 2960 20 40 0 370 2960/8=370

说明

  • 原始数据总长 = 2980 字节。

  • 第一片:携带数据 0, 1479(共 1480 字节),IP 报头总长度 = 1500,MF=1,片偏移=0。

  • 第二片:携带数据 1480, 2959(共 1480 字节),IP 报头总长度 = 1500,MF=1,片偏移=185(因为 1480 ÷ 8 = 185)。

  • 第三片:携带数据 2960, 2979(共 20 字节),IP 报头总长度 = 40,MF=0,片偏移=370(因为 2960 ÷ 8 = 370)。

2. 组装过程(接收方)

接收方可能收到乱序的分片,例如顺序是:分片2、分片1、分片3。

步骤 1:识别属于同一原始数据报的分片

根据 IP 头中的 源 IP、目的 IP、协议、标识符 四个字段将分片归类。此处假设所有分片的标识符(Identification)相同(如 0x1234)。

步骤 2:按片偏移排序

收到的分片信息:

分片 片偏移 MF 数据长度
2 185 1 1480
1 0 1 1480
3 370 0 20

排序后:

分片 片偏移 MF 数据长度 起始字节 结束字节(不含)
1 0 1 1480 0 1480
2 185 1 1480 1480 2960
3 370 0 20 2960 2980

步骤 3:检查是否收全

  • 最后一个分片的 MF=0,其结束位置 = 片偏移 × 8 + 数据长度 = 370×8 + 20 = 2960 + 20 = 2980 字节。

  • 这正好等于原始数据总长度(所有分片数据之和)。

  • 收全条件满足。

步骤 4:重组数据

创建一个 2980 字节的缓冲区,按顺序复制:

  • 复制分片1 的数据(1480 字节)到缓冲区 0, 1479

  • 复制分片2 的数据(1480 字节)到缓冲区 1480, 2959

  • 复制分片3 的数据(20 字节) 到缓冲区 2960, 2979

步骤 5:构建完整的 IP 数据报

  • 取出第一个分片的 IP 头部(或重建一个),将其中的 总长度 修改为 3000(20 头部 + 2980 数据)。

  • 清除分片标志:MF=0,片偏移=0。

  • 重新计算 IP 头部校验和。

  • 将重组后的数据附加到头部后面。

这样就得到了一个完整的 3000 字节 IP 数据报,可以交付给上层协议(如 TCP/UDP)。

注意:

  • 如果某个分片丢失(例如一直没收到 MF=0 的分片),接收方会启动一个重组超时定时器(典型值 30 秒)。超时后丢弃已收到的分片,并可能发送 ICMP 超时 消息(类型 11,代码 1)。

  • 传输层(TCP/UDP)完全感知不到分片的存在 ------ 它们收到的就是已经组装好的完整报文。

相关推荐
Zevalin爱灰灰1 小时前
makefile从入门到实战 第一章 认识makefile(一)
linux·makefile
闪电悠米1 小时前
黑马点评-秒杀优化-04_lua_and_db_fallback
服务器·开发语言·网络·数据库·缓存·junit·lua
Shadow(⊙o⊙)1 小时前
进程间通信0.0-pipe()匿名管道,详细分析进程池调度队列执行逻辑,进程池模拟实现。
linux·运维·服务器·开发语言·c++
CQU_JIAKE1 小时前
6.6aaaaaa
linux·运维·服务器
Apibro1 小时前
【Linux】Qt Creator 中文输入法
linux·qt
smallswan2 小时前
第十四 算数运算
linux·服务器·前端
Yang96112 小时前
风场光伏光缆分缆测损,DM-40A 光通信综合测试仪高效运维
网络·能源
丑过三八线2 小时前
Umi 配置文件 .umirc.ts 详解
linux·运维·ubuntu·react.js
努力搬砖的咸鱼2 小时前
容器编排底层原理:Kubernetes 网络模型与 CNI 插件
网络·微服务·云原生·容器·架构·kubernetes