7. WireShark分析IP数据包格式

我用最通俗的方式,把这个图"拆碎了讲",帮你彻底搞懂"一行一行到底是什么""为什么要这么画"。


一、先搞懂:图里的"行",到底是什么?

一句话:图里的每一行,代表 32 个比特(也就是 4 个字节)的二进制数据

你可以把IP报文想象成一串连续的0和1(比如 0100010100000000...),电脑/网络设备处理这串数据的时候,是按32个比特(4字节)为一组来读的,这就是图里的"行"。

最上面标了 0、4、8、16、19、24、31,这些是比特的序号,从0到31,一共32个比特,刚好凑成一行。

举个例子,第一行的32个比特,被分成了4个部分:

  • 第0-3位(4个比特):版本号
  • 第4-7位(4个比特):首部长度
  • 第8-15位(8个比特):区分服务
  • 第16-31位(16个比特):总长度

就像一张32格的表格,协议规定了"哪几格用来存什么数据",设备读的时候,直接按这个规则取数据就行。


二、用"快递单"比喻,秒懂这个结构

把IP报文当成一个快递包裹

  • 整个包裹 = IP数据报
  • 包裹里的货物 = 数据部分(黄色部分)
  • 包裹外面的快递单 = 首部(红色部分)

而这个图,就是快递单的标准模板

  • 快递单的每一行,都印好了"格子",规定了哪些格子写什么信息
  • 比如第一行:前4格写"版本号"(相当于"快递单版本"),接下来4格写"快递单长度",再接下来8格写"服务类型"(比如加急/普通件),最后16格写"整个包裹的总重量"
  • 快递员/快递系统,看到这张标准模板,就知道该从哪几格取信息,不会乱读

三、逐行拆解:每一行的32比特里,都装了什么?

我把图里的每一行,按"32比特的组成"拆给你看,你就知道为什么要这样分了:

第1行(32比特)

比特位置 字段名 长度 作用
0-3 版本 4位 标识是IPv4还是IPv6
4-7 首部长度 4位 说明快递单(首部)占多少
8-15 区分服务 8位 标记优先级(加急/普通)
16-31 总长度 16位 整个包裹(IP包)的大小

→ 这一行凑起来刚好32位,都是"包裹的基础信息",设备读第一行,就知道"这是个什么版本的包、有多大、服务优先级"。


第2行(32比特)

比特位置 字段名 长度 作用
0-15 标识 16位 给包一个唯一编号
16-18 标志 3位 控制包能不能分片
19-31 片偏移 13位 分片后,说明自己是第几片

→ 这一行也是32位,都是"分片重组相关的信息",如果包裹太大被拆成好几份,靠这些信息拼回去。


第3行(32比特)

比特位置 字段名 长度 作用
0-7 生存时间(TTL) 8位 包最多能经过多少个路由器
8-15 协议 8位 里面装的是TCP还是UDP
16-31 首部检验和 16位 校验快递单有没有被改坏

→ 这一行32位,是"转发和校验信息",路由器靠这些判断要不要转发、包有没有损坏。


第4行(32比特)

  • 全部32位 = 源IP地址(发件人地址)

第5行(32比特)

  • 全部32位 = 目的IP地址(收件人地址)

→ 这两行都是纯地址,刚好各占32位,是快递单上最重要的"收发件地址"。


第6行(32比特,可变部分)

  • 前半部分:可选字段(长度可变,最多40字节)
  • 后半部分:填充(如果前面的可选字段没凑够32位,用0补满)

→ 这一行是可选扩展,平时用得很少,主要是为了兼容未来的新功能。


四、为什么一定要按"32位一行"来设计?

这不是随便画的,是为了硬件和软件都能高效处理,核心原因有3个:

1. 硬件处理效率高

早期的CPU、路由器,处理数据的基本单位就是32位(4字节)。按32位对齐,设备可以直接"按行读取"数据,不用拆分,处理速度更快。

就像快递员拿快递,一次拿一摞(固定数量),比一个一个拿效率高多了。

2. 字段宽度是"按需分配",不浪费空间

每个字段需要的比特数,是根据它的用途定的:

  • 版本号:只需要4位(0-15,足够表示IPv4/IPv6)
  • 总长度:需要16位(最大能表示65535字节,满足IP包的最大长度)
  • IP地址:需要32位(IPv4地址就是32位的)

把这些不同长度的字段,凑成32位一行,刚好不浪费空间,也不用额外的处理。

3. 标准化,所有设备都能看懂

IP协议是全球通用的,这个"按32位划分的格式"是固定的,所有路由器、电脑、手机,都按同一个规则解析IP包。就像所有快递都用统一的快递单模板,不管哪个快递公司都能看懂。


五、结合嵌入式开发,给你看代码里的对应关系

你在C语言里定义IP首部的结构体,和这个图是1:1对应的,用的就是"位域"来划分字段:

c 复制代码
struct iphdr {
    // 第1行(32位)
    uint8_t  version:4;   // 0-3位:版本(4位)
    uint8_t  ihl:4;       // 4-7位:首部长度(4位)
    uint8_t  tos;         // 8-15位:区分服务(8位)
    uint16_t tot_len;     // 16-31位:总长度(16位)

    // 第2行(32位)
    uint16_t id;          // 0-15位:标识(16位)
    uint16_t frag_off;    // 16-18位标志 + 19-31位片偏移(共16位)

    // 第3行(32位)
    uint8_t  ttl;         // 0-7位:TTL(8位)
    uint8_t  protocol;    // 8-15位:协议(8位)
    uint16_t check;       // 16-31位:首部校验和(16位)

    // 第4-5行(各32位)
    uint32_t saddr;       // 源IP(32位)
    uint32_t daddr;       // 目的IP(32位)
};

你看,这个结构体的内存布局,和图里的"一行一行"完全对应,编译器会按32位对齐来存储,和IP协议的格式一模一样。


六、总结

  1. 图里的"行",不是逻辑上的"分层" ,而是物理上的32比特数据块,是设备处理IP包的基本单位。
  2. 每一行里,被划分成了多个不同长度的字段,每个字段负责一个特定的功能,凑起来刚好32位。
  3. 这种设计是为了高效、标准化,让所有设备都能快速、统一地解析IP包。

首部是24个字节吗?

❌ 不对哦,IP首部的最小长度是20字节,不是24字节,而且它的长度是可变的,范围在20~60字节之间。我结合你之前的"行"的概念,给你算清楚:


一、先算"行"对应的字节数

图里的每一行,是 32比特(bit) ,而 8比特 = 1字节,所以:

1行 = 32 ÷ 8 = 4字节


二、数清楚"固定部分"的行数

IP首部的固定部分(所有IP包都必须有的部分),对应图里的前5行:

行号 内容 字节数
第1行 版本+首部长度+区分服务+总长度 4字节
第2行 标识+标志+片偏移 4字节
第3行 生存时间+协议+首部检验和 4字节
第4行 源IP地址 4字节
第5行 目的IP地址 4字节

所以固定部分的总长度是:5行 × 4字节/行 = 20字节,这是IP首部的最小长度,也是我们平时上网的IP包最常见的情况。


三、"可变部分"不是固定的4字节

你图里的第6行"可选字段+填充",是可选的、长度可变的,不是固定占4字节:

  • 可选字段是用来扩展特殊功能的(比如安全、调试选项),实际网络中几乎不用,所以大部分IP包的可变部分长度为0,也就是没有这部分。
  • 如果用了可选字段,长度也必须是4字节的整数倍(不够的话用填充位补0),最多可以到40字节(因为整个首部最大60字节,60-20=40)。

四、为什么会有"24字节"的误解?

你可能是把"固定部分+1行可变部分"算成了 6行 × 4字节 = 24字节,但这只是一种特殊情况(比如IP包带了4字节的可选字段),不是所有IP包的首部都是24字节。


五、补充:首部长度字段的作用

图里的"首部长度(IHL)"字段,就是用来告诉设备"这个IP包的首部到底有多长"的:

  • 这个字段占4比特,单位是4字节
  • 最小值是5(二进制0101) → 5×4=20字节(只有固定部分,无可选字段,最常见)。
  • 最大值是15(二进制1111) → 15×4=60字节(固定部分+40字节可选字段,极少用)。

举个嵌入式开发里的例子

在C语言里,IP首部的结构体定义是这样的:

c 复制代码
struct iphdr {
    uint8_t  version:4;   // 版本
    uint8_t  ihl:4;       // 首部长度
    uint8_t  tos;         // 区分服务
    uint16_t tot_len;     // 总长度
    uint16_t id;          // 标识
    uint16_t frag_off;    // 标志+片偏移
    uint8_t  ttl;         // 生存时间
    uint8_t  protocol;    // 协议
    uint16_t check;       // 首部检验和
    uint32_t saddr;       // 源IP
    uint32_t daddr;       // 目的IP
};

可以算一下,这个结构体的大小是 20字节,正好对应固定部分的长度。可选字段是在这个结构体后面额外拼接的,不是固定包含的。


简单说:IP首部最小20字节,最大60字节,20字节是所有IP包都有的固定部分,24字节只是带了少量可选字段的特殊情况。

相关推荐
带土11 小时前
8. TCP 协议概述
网络·网络协议·tcp/ip
weixin_427771612 小时前
http 请求body加密
网络·网络协议·http
小杨勇敢飞3 小时前
记录一次 VMware 虚拟机固定 IP 后,FinalShell 连接不上的排查过程
网络·网络协议·tcp/ip
weixin_6042366711 小时前
华三 路由器 极简核心配置
运维·服务器·网络·h3c·h3c路由器
换个昵称都难14 小时前
webrtc 音频模块FEC模块
网络·音视频·webrtc
youngerwang15 小时前
【从搬运工到协处理器:网卡芯片架构、算法、验证与边缘演进深度剖析】
网络·算法·架构·芯片
KaMeidebaby15 小时前
卡梅德生物技术快报|纯化重组蛋白实操详解
人工智能·python·tcp/ip·算法·机器学习
zjun100116 小时前
TCP专栏-4.四次挥手
网络协议·tcp/ip
智慧光迅AINOPOL17 小时前
校园在线巡课系统方案:督导全覆盖
网络·全光网解决方案·全光网·校园全光网·校园全光网解决方案