← 网络基础学习第 3 / 55 章入门35 分钟

模块零 · 全景与基础

封装与解封装

「封装」是网络里最核心的机制 —— 数据每往下走一层,就被套上一层「信封」。这一章用一个能亲手做的实验,量出信封到底有多厚,而不是只给你一个比喻。

本章要解决的问题:「封装」是网络里最核心的机制 —— 数据每往下走一层,就被套上一层「信封」。这一章用一个能亲手做的实验,量出信封到底有多厚,而不是只给你一个比喻。

本章的证据来源:历史实测记录(用 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 头+ 20120段 segment
网络层加头IP 头+ 20140包 packet
链路层加头加尾以太网头 + 帧尾+ 14 + 4158帧 frame

在无选项IPv4/TCP、无VLAN的假设下,100字节应用数据形成158字节以太网MAC帧;完整介质占用还要考虑前导码、SFD与帧间隙。 多出来的 58 字节全是"信封"。

实测:亲手量出信封有多厚

上面那套加法是"应该有多厚"。能不能测出来?能 —— 而且不用装任何抓包软件。

原理:ping 命令有一个 -f 参数,意思是禁止分片(Don't Fragment)。开启它,如果一个包超过了链路的 MTU,系统就没法把它发出去,会直接报错。于是我们可以从两头往中间逼近,找出这个临界值。

实验一:走 WLAN 网卡(MTU = 1500)powershell
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 字节
实验二:走 FlClash 虚拟网卡(MTU = 9000)powershell
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 题 · 先自己答,再展开对照

  1. 在 MTU 为 1500 的链路上,ping -f -l 1472 成功而 -l 1473 失败,这个实验测出的是什么?
    在已知接口 MTU=1500、无 IPv4 选项且 ICMP Echo 能响应的前提下,临界载荷1472与20+8字节头部一致。仅测得临界载荷不能同时独立证明 MTU 和头部长度。
  2. 为什么换成 Wi-Fi 或者光纤,这 28 字节的开销不会变?
    此计算针对无选项 IPv4+ICMP Echo,因此上层头部不随介质更换;链路封装、IPv6或隧道开销仍可能不同。
  3. 一个交换机和一个 L7 负载均衡器都能转发数据,它们"看到"的信息有什么不同?
    普通二层转发主要使用 MAC;L7 可使用解密后的 HTTP 路径和头部。按路径选后端不要求先收完整请求体,性能不能只由层号判断。
  4. 分片和封装的关键区别是什么?
    封装增加协议控制信息,IP分片拆分一个数据报;内存是否拷贝属于实现。分片丢失导致重组失败,IP自己不重传。
  5. ping -l 1472 里的 1472 指的是哪一部分的长度?它为什么不包含 ICMP 头?
    指 ICMP 数据部分的长度,也就是 ping 报文里真正携带的那段"填充数据"。ICMP 头(8 字节)是协议自己加的,不归 -l 管。所以实际发出去的 IP 包长 = 1472 + 8(ICMP 头)+ 20(IP 头)= 1500,正好等于 MTU。
  6. 本机平均每个包只有 561 字节,远小于 MTU 1500。这对网络利用率意味着什么?
    必须先核对计数口径和统计时间。即使确认平均帧较小,也只能讨论报头占比,不能单凭平均长度判断总带宽利用率或建议所有应用攒包。

参考资料与适用范围

修订核对日期:2026-10-13。规则按所列协议与实现范围理解;文中的原始命令输出是历史观察,不表示本次重新实测。跨版本、代理/隧道及不同捕获位置需要另行核对。

正文源自 m0-03-封装与解封装.md · 共 11 节 · 6 道自测题