《Linux高性能服务器编程》——2.3 IP分片

简介: 本节书摘来自华章计算机《Linux高性能服务器编程》一书中的第2章,第2.3节,作者 游双,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.3 IP分片

前文曾提到,当IP数据报的长度超过帧的MTU时,它将被分片传输。分片可能发生在发送端,也可能发生在中转路由器上,而且可能在传输过程中被多次分片,但只有在最终的目标机器上,这些分片才会被内核中的IP模块重新组装。

IP头部中的如下三个字段给IP的分片和重组提供了足够的信息:数据报标识、标志和片偏移。一个IP数据报的每个分片都具有自己的IP头部,它们具有相同的标识值,但具有不同的片偏移。并且除了最后一个分片外,其他分片都将设置MF标志。此外,每个分片的IP头部的总长度字段将被设置为该分片的长度。

以太网帧的MTU是1500字节(可以通过ifconfig命令或者netstat命令查看),因此它携带的IP数据报的数据部分最多是1480字节(IP头部占用20字节)。考虑用IP数据报封装一个长度为1481字节的ICMP报文(包括8字节的ICMP头部,所以其数据部分长度为1473字节),则该数据报在使用以太网帧传输时必须被分片,如图2-2所示。

图2-2中,长度为1501字节的IP数据报被拆分成两个IP分片,第一个IP分片长度为1500字节,第二个IP分片的长度为21字节。每个IP分片都包含自己的IP头部(20字节),且第一个IP分片的IP头部设置了MF标志,而第二个IP分片的IP头部则没有设置该标志,因为它已经是最后一个分片了。原始IP数据报中的ICMP头部内容被完整地复制到了第一个IP分片中。第二个IP分片不包含ICMP头部信息,因为IP模块重组该ICMP报文的时候只需要一份ICMP头部信息,重复传送这个信息没有任何益处。1473字节的ICMP报文数据的前1472字节被IP模块复制到第一个IP分片中,使其总长度为1500字节,从而满足MTU的要求;而多出的最后1字节则被复制到第二个IP分片中。

image

需要指出的是,ICMP报文的头部长度取决于报文的类型,其变化范围很大。图2-2以8字节为例,因为后面的例子用到了ping程序,而ping程序使用的ICMP回显和应答报文的头部长度是8字节。

为了看清楚IP分片的具体过程,考虑从ernest-laptop来ping机器Kongming20,每次传送1473字节的数据(这是ICMP报文的数据部分)以强制引起IP分片,并用tcpdump抓取这一过程中双方交换的数据包。具体操作过程如下:

$ sudo tcpdump -ntv -i eth0 icmp        #只抓取ICMP报文
$ ping Kongming20 –s 1473            #用-s选项指定每次发送1473字节的数据

下面我们考察tcpdump输出的一个IP数据报的两个分片,其内容如下:

1. IP(tos 0x0, ttl 64, id 61197, offset 0, flags [+], proto ICMP (1), length 1500)
     192.168.1.108 > 192.168.1.110: ICMP echo request, id 41737, seq 1, length 1480
2. IP(tos 0x0, ttl 64, id 61197, offset 1480, flags [none], proto ICMP (1), length 21)
     192.168.1.108 > 192.168.1.110: icmp

这两个IP分片的标识值都是61197,说明它们是同一个IP数据报的分片。第一个分片的片偏移值为0,而第二个则是1480。很显然,第二个分片的片偏移值实际上也是第一个分片的ICMP报文的长度。第一个分片设置了MF标志以表示还有后续分片,所以tcpdump输出“flags[+]”。而第二个分片则没有设置任何标志,所以tcpdump输出“flags[none]”。这个两个分片的长度分别为1500字节和21字节,这与图2-2描述的一致。

最后,IP层传递给数据链路层的数据可能是一个完整的IP数据报,也可能是一个IP分片,它们统称为IP分组(packet)。本书如无特殊声明,不区分IP数据报和IP分组。

相关文章
|
1月前
|
算法 Linux C++
【Linux系统编程】解析获取和设置文件信息与权限的Linux系统调用
【Linux系统编程】解析获取和设置文件信息与权限的Linux系统调用
29 0
|
1月前
|
算法 Linux C++
【Linux系统编程】深入解析Linux中read函数的错误场景
【Linux系统编程】深入解析Linux中read函数的错误场景
205 0
|
1月前
|
Linux API C语言
【Linux系统编程】深入理解Linux 组ID和附属组ID的查询与设置
【Linux系统编程】深入理解Linux 组ID和附属组ID的查询与设置
34 0
【Linux系统编程】深入理解Linux 组ID和附属组ID的查询与设置
|
1月前
|
存储 算法 Linux
【Linux系统编程】深入理解Linux目录扫描函数:scandir目录函数(按条件扫描目录
【Linux系统编程】深入理解Linux目录扫描函数:scandir目录函数(按条件扫描目录
39 0
|
1月前
|
存储 算法 Linux
【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构
【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构
45 0
|
1天前
|
消息中间件 关系型数据库 MySQL
Linux:开源之魅与编程之道
Linux:开源之魅与编程之道
9 1
|
1天前
|
Ubuntu Linux
Linux(Ubuntu)系统临时IP以及静态IP配置(关闭、启动网卡等操作)
请注意,以上步骤是在临时基础上进行配置的。如果要永久保存静态IP地址,通常还需要修改 `/etc/network/interfaces`文件,以便在系统重启后保持配置。同时,确保备份相关配置文件以防止出现问题。
12 1
|
2天前
|
监控 Linux 网络安全
Linux服务器如何查询连接服务器的IP
【4月更文挑战第15天】Linux服务器如何查询连接服务器的IP
9 1
|
3天前
|
Linux
Linux(23) Linux 4G模块不能获取IP排查思路
Linux(23) Linux 4G模块不能获取IP排查思路
11 0
|
18天前
|
Linux 开发者
Linux文件编程(open read write close函数)
通过这些函数,开发者可以在Linux环境下进行文件的读取、写入和管理。 买CN2云服务器,免备案服务器,高防服务器,就选蓝易云。百度搜索:蓝易云
85 4