模块零 · 全景与基础
封装与解封装
「封装」是网络里最核心的机制 —— 数据每往下走一层,就被套上一层「信封」。这一章用一个能亲手做的实验,量出信封到底有多厚,而不是只给你一个比喻。
本章要解决的问题:「封装」是网络里最核心的机制 —— 数据每往下走一层,就被套上一层「信封」。这一章用一个能亲手做的实验,量出信封到底有多厚,而不是只给你一个比喻。
本章的证据来源:历史实测记录(用 ping -f -l 逐字节逼近 MTU 边界、网卡字节计数器)。头部字段的长度规定出自 RFC 791(IPv4)与 RFC 792(ICMP)。
先从一个例子理解概念
把信放进信封、写收件地址、再装进快递袋,信的内容之外增加了配送信息。网络发送数据也要增加不同用途的控制信息。
原内容与附加信息:载荷、头部与尾部
真正要交给下一环节处理的内容叫载荷。前面加的控制信息叫头部,后面加的叫尾部。比如“发给谁、里面是什么”通常写在头部。
逐层添加与取出:封装、解封装
发送时添加协议规定的头尾,叫封装;接收时处理并移除相应头尾,把内容交上层,叫解封装。这是格式规则,不规定一定拷贝或共用哪块内存。
每段线路的容量:MTU
一条链路能承载的IP包大小有上限,常用MTU(最大传输单元)描述。装不下时如何处理,取决于包类型与协议。以太网的MTU不包括它自己的帧头和帧尾。
观察往返的工具:ping与ICMP
ping是发送“请回应”的探测并等待回复的工具;它通常使用ICMP,一种IP层的诊断与差错通知协议。这里测ICMP包,不是测TCP数据,所以头部大小不能混用。
下面再用这些概念看原理、命令和结果。规范与官方资料列在本章末尾,类比只帮助理解,不代替协议规则。
先看寄快递的过程
上一章说"分层就是每层只管一件事"。那"每层加自己的包头"具体是什么样?用寄快递类比:
你写的信 ← 你要传的数据
↓ 装进信封,写上收件人姓名
信封 ← 加了一层「头」,写明给谁
↓ 装进快递袋,贴上运单(寄件城市、目的城市、单号)
快递袋 ← 又加了一层「头」
↓ 装进车厢
车厢 ← 又加了一层这个类比描述分层职责,不是说设备在技术上只能看到一层。
分拣中心只看运单上的目的城市,不关心信封里写的是什么,也不会为了分拣去拆信封。到了目的地城市,网点只看信封上的姓名,不关心里面那封信用的是中文还是英文。
网络就是这样工作的。
网络里的「信封」:逐层加头
假设你的程序要发 100 字节的数据:
应用层数据(100 字节)
↓ 传输层加头:TCP 头 20 字节 → 现在叫「段」(segment)
↓ 网络层加头:IP 头 20 字节 → 现在叫「包」(packet)
↓ 链路层加头加尾:以太网头 14 + 帧尾 4 字节 → 现在叫「帧」(frame)
↓ 变成电信号 → 现在叫「比特」(bit)换成表格看得更清楚(这是同一件事的另一种记法):
| 步骤 | 加上的东西 | 长度 | 累计 | 这一层的产物叫 |
|---|---|---|---|---|
| 应用层产出 | —(原始数据) | 100 字节 | 100 | 数据 |
| 传输层加头 | TCP 头 | + 20 | 120 | 段 segment |
| 网络层加头 | IP 头 | + 20 | 140 | 包 packet |
| 链路层加头加尾 | 以太网头 + 帧尾 | + 14 + 4 | 158 | 帧 frame |
在无选项IPv4/TCP、无VLAN的假设下,100字节应用数据形成158字节以太网MAC帧;完整介质占用还要考虑前导码、SFD与帧间隙。 多出来的 58 字节全是"信封"。
实测:亲手量出信封有多厚
上面那套加法是"应该有多厚"。能不能测出来?能 —— 而且不用装任何抓包软件。
原理:ping 命令有一个 -f 参数,意思是禁止分片(Don't Fragment)。开启它,如果一个包超过了链路的 MTU,系统就没法把它发出去,会直接报错。于是我们可以从两头往中间逼近,找出这个临界值。
ping -f -l 1472 192.168.31.1
ping -f -l 1473 192.168.31.1实测输出:
--- ping -f -l 1472 192.168.31.1 ---
Pinging 192.168.31.1 with 1472 bytes of data:
Reply from 192.168.31.1: bytes=1472 time=2ms TTL=64
← 成功!
--- ping -f -l 1473 192.168.31.1 ---
Pinging 192.168.31.1 with 1473 bytes of data:
Packet needs to be fragmented but DF set.
← 失败:需要分片,但设置了禁止分片载荷 1472 能过,1473 不能过。 所以信封的厚度是:
MTU(1500) − 载荷上限(1472) = 28 字节ping -f -l 8972 198.18.0.2
ping -f -l 8973 198.18.0.2实测输出:
--- ping -f -l 8972 198.18.0.2 ---
Reply from 198.18.0.2: bytes=8972 time<1ms TTL=128 ← 成功
--- ping -f -l 8973 198.18.0.2 ---
Packet needs to be fragmented but DF set. ← 失败MTU(9000) − 载荷上限(8972) = 28 字节两次实验说明了两件事
第一,这两次 IPv4 Echo 探测采用相同的头部格式。 1500 的网卡和 9000 的网卡,头部开销都是 28 字节。因为头部大小是由协议决定的,不是由物理介质决定的 —— IPv4 无选项头 20 字节加 ICMP Echo 头 8 字节为 28;IPv6、IP 选项和隧道封装需要另外计算。
第二,我们测出了 28 这个数,但还不知道它是怎么构成的。 这 28 字节拆开是:
| 部分 | 长度 | 出处 |
|---|---|---|
| IP 头 | 20 字节 | RFC 791 规定的最短 IPv4 头 |
| ICMP 头 | 8 字节 | RFC 792 规定(ping 用的就是 ICMP) |
| 合计 | 28 字节 |
解封装:对方一层层脱掉信封
发送方层层加头,接收方就层层脱头,顺序正好相反:
网卡收到电信号
↓ 拼成帧
链路层:检查帧头的「目的 MAC 地址」——是给我的吗?
↓ 是 → 脱掉以太网头和帧尾,把里面的东西交给网络层
网络层:检查 IP 头的「目的 IP 地址」——是给我的吗?
↓ 是 → 脱掉 IP 头,把里面的东西交给传输层
传输层:检查 TCP 头的「目的端口」——是给哪个程序的?
↓ 找到对应的程序 → 脱掉 TCP 头,把数据交给它
应用层:拿到原始数据分层规定主要职责,不禁止实现查看其他层。 NAT、防火墙、深度检测和多层交换等设备可检查多层字段;是否能理解内容还取决于加密。
这个"只读自己那层"的特性,直接决定了各种网络设备的能力:
| 设备 | 能看到哪一层 | 所以它能做什么 |
|---|---|---|
| 集线器 | 物理层 | 只会把信号复制一份发给所有口 |
| 交换机 | 链路层 | 看 MAC 地址,知道该从哪个口转发 |
| 路由器 | 网络层 | 看 IP 地址,能跨网络选路 |
| 防火墙 | 传输层及以上 | 看端口,能按程序放行或拦截 |
| L7 负载均衡 | 应用层 | 看 HTTP 路径,能把 /api 和 /static 分到不同服务器 |
一个必须澄清的误解
封装规定报文格式,不规定必须怎样安排内存。
实现可能预留头部空间、引用多块缓冲区、执行拷贝,或交给网卡做分段/校验卸载。不能把“所有层始终共用同一块内存”和“只有分片会拷贝”说成协议标准。
分片是把一个 IP 数据报拆成能通过链路的多个数据报;分段是 TCP 按字节流和 MSS 组织 TCP 段。它们是不同层的操作。IP 重组缺一片就无法交付该数据报,但重传由 TCP 或应用决定,UDP 可能不重传。RFC 791 §1.4、§3.2
实测:网卡计数器里的真实规模
定义是一回事,真实流量是另一回事。看本机 WLAN 网卡开机至今的累计统计:
ReceivedBytes : 187065778945 收到 1870 亿字节
ReceivedUnicastPackets : 333281415 收到 3.3 亿个包
SentBytes : 327653373263 发出 3276 亿字节
SentUnicastPackets : 446155662 发出 4.5 亿个包用两个数字相除,得到平均每个包有多大:
收:187065778945 ÷ 333281415 ≈ 561 字节/包
发:327653373263 ÷ 446155662 ≈ 734 字节/包这只是两个历史计数器的比值,不是已核实的逐包载荷平均值。
字节与包计数的覆盖口径未核对,且分母这里只用单播计数,不能直接与以太网 MAC 帧长度 1518 比较。实际只有 561,与存在较多短报文相容,但仅凭这组混合计数不能精确统计短报文占比 —— 域名查询、握手、确认、心跳,这些包携带的数据很少,但头部一个字节都省不了。
常见误解
误解一:"封装只是教学比喻"
不是。头部字段是真实存在的字节,就在网线上传输的数据里。上面 ping 实验测出的 28 字节就是它们的物理证据。
误解二:"路由器会拆开信封看里面是什么"
正常情况下不会。普通转发主要按IP头决策;即使设备读取载荷,正确TLS加密仍保护其机密性 —— 中间设备看得到 IP 和端口,看不到内容。《应用层》模块讲 TLS 时会说明"中间人能看到什么、看不到什么"。
误解三:"层数越多越慢,所以应该减少层数"
加头确实有开销,但现代网络里这个开销占比很小(满载帧约 3.8%)。而分层带来的好处是任何一层都能独立演进。用几个百分点的带宽换取整个互联网的可升级性,这个交易极其划算。
本章小结
| 结论 | 性质 |
|---|---|
| 封装增加协议头尾,解封装在接收时处理这些字段 | 协议格式 |
| IPv4无选项+ICMP Echo的头部合计28字节 | 标准与计算 |
| DF探测结果需结合已知MTU、协议版本、是否收到响应解释 | 实验条件 |
| 缓冲区复用与拷贝由实现决定 | 实现边界 |
| 两个统计计数的比值不能替代逐包抓取与口径核对 | 证据限制 |
自测题
6 题 · 先自己答,再展开对照
在 MTU 为 1500 的链路上,
ping -f -l 1472成功而-l 1473失败,这个实验测出的是什么?在已知接口 MTU=1500、无 IPv4 选项且 ICMP Echo 能响应的前提下,临界载荷1472与20+8字节头部一致。仅测得临界载荷不能同时独立证明 MTU 和头部长度。为什么换成 Wi-Fi 或者光纤,这 28 字节的开销不会变?
此计算针对无选项 IPv4+ICMP Echo,因此上层头部不随介质更换;链路封装、IPv6或隧道开销仍可能不同。一个交换机和一个 L7 负载均衡器都能转发数据,它们"看到"的信息有什么不同?
普通二层转发主要使用 MAC;L7 可使用解密后的 HTTP 路径和头部。按路径选后端不要求先收完整请求体,性能不能只由层号判断。分片和封装的关键区别是什么?
封装增加协议控制信息,IP分片拆分一个数据报;内存是否拷贝属于实现。分片丢失导致重组失败,IP自己不重传。ping -l 1472里的 1472 指的是哪一部分的长度?它为什么不包含 ICMP 头?指 ICMP 数据部分的长度,也就是 ping 报文里真正携带的那段"填充数据"。ICMP 头(8 字节)是协议自己加的,不归-l管。所以实际发出去的 IP 包长 = 1472 + 8(ICMP 头)+ 20(IP 头)= 1500,正好等于 MTU。本机平均每个包只有 561 字节,远小于 MTU 1500。这对网络利用率意味着什么?
必须先核对计数口径和统计时间。即使确认平均帧较小,也只能讨论报头占比,不能单凭平均长度判断总带宽利用率或建议所有应用攒包。
参考资料与适用范围
- RFC 791 §1.4、§3.1–3.2:IPv4格式、分片与重组
- RFC 792:IPv4 ICMP Echo与差错类型
- RFC 1191:IPv4路径MTU发现
- IEEE 802.3as官方教学说明,第14–18页:基本及Q标签帧格式与长度
- Wireshark官方卸载说明:捕获位置、分段与校验
修订核对日期:2026-10-13。规则按所列协议与实现范围理解;文中的原始命令输出是历史观察,不表示本次重新实测。跨版本、代理/隧道及不同捕获位置需要另行核对。