Files
cs-note/hhs/NETWORK/01-基础概念/02-数据封装与解封装.md
T
2026-05-24 11:42:38 +08:00

5.8 KiB
Raw Blame History

tags, create time
tags create time
计算机网络
数据封装
网络分层
2026-05-17 22:20

数据封装与解封装

概述

数据在发送端逐层加上头部(Header),就像装快递盒子:最里层是商品,外面一层一层套纸箱、贴面单、打托盘。到达接收端后,每一层剥掉自己的那层包装,只把原始内容交给上层处理。这个"套娃+拆箱"的过程就是 封装(Encapsulation) 和 解封装(Decapsulation)。

[!QUESTION] 为什么每层都要加头? 因为每层需要知道如何管理自己的事务——传输层关心连接状态,网络层关心路由寻址,链路层关心物理介质。这些元信息必须跟在数据前面,让每一层都能正确解读并转发。

数据包尺寸变化轨迹

以发送一个 HTTP GET 请求为例,追踪尺寸变化:

层级 操作 数据结构 新增首部大小 累计大小
应用层 HTTP GET 报文 GET / HTTP/1.1\r\nHost: example.com\r\n\r\n — ~40 bytes
传输层 (TCP) + TCP Header Segment 20 bytes ~60 bytes
网络层 (IP) + IP Header Packet 20 bytes (IPv4) ~80 bytes
链路层 (Ethernet) + Eth Header + FCS Frame 14 + 4 = 18 bytes ~98 bytes
flowchart LR
    H["HTTP GET 40B"] --> T["+ TCP Header 20B<br/>Segment 60B"]
    T --> I["+ IP Header 20B<br/>Packet 80B"]
    I --> E["+ Ethernet HDR 14B + FCS 4B<br/>Frame 98B"]
    E --> B["98 个 Bit 在网线上传输"]

    style H fill:#DDA0DD
    style T fill:#FFD700
    style I fill:#87CEEB
    style E fill:#98FB98

发送端:逐层封装

sequenceDiagram
    participant App as HTTP 应用
    participant TCP as TCP Socket
    participant IP as 网络层 IP
    participant ETH as 以太网驱动

    App->>TCP: write("GET / HTTP/1.1...")
    Note over TCP: 分配 seq/ack, state=ESTABLISHED
    TCP->>IP: 传递 Segment (daddr=x.x.x.x, sport=1234, dport=80)
    Note over IP: 查路由表 → 下一跳网关
    IP->>ETH: 传递 Packet (dst_mac=?, src_ip=192.168.1.100, dst_ip=93.184.216.34)
    Note over ETH: ARP 解析 → dst_mac=aabb.ccdd.eeff
    ETH->>ETH: 拼接 源MAC+目的MAC+EtherType+Payload+FCS
    ETH-->>App: sendto() 返回 → 帧已发出 ✅

Ethernet II 帧完整结构

Offset  Size   Field              说明
──────  ────   ─────────────────  ─────────────────────────────
0       6      Dest MAC Address   目标 MAC 地址
6       6      Source MAC Address 源 MAC 地址
12      2      EtherType          0x0800=IPv4 / 0x86DD=IPv6 / 0x0806=ARP
14      N      Payload            IP 包(最大 1500 字节)
14+N    4      FCS                CRC-32 帧校验序列(接收端自动验证)

总长度范围:64 ~ 1518 bytes(不含 VLAN Tag;有 VLAN Tag 则上限 1522)。

[!note] MTU = 1500 是什么意思? MTU(Maximum Transmission Unit)是链路层允许的最大 Payload 大小,即 IP 包的最大体积。超过会被分片(Fragmentation),但分片会降低性能且增加丢包风险——这也是现代应用层(如 TLS、gRPC)倾向于小包传输的原因。

接收端:逐层解封装

sequenceDiagram
    participant ETH as 网卡收到 Frame
    participant IP as 剥离以太网头
    participant TCP as 剥离 TCP 头
    participant App as 提取 HTTP 数据

    ETH->>IP: 校验 FCS OK → 取 EtherType=0x0800 → 剥离以太网头
    IP->>TCP: 校验 IP Checksum → 取 Protocol=6(TCP) → 剥离 IP 头
    TCP->>App: 按 Sequence Number 重组 → 剥离 TCP 头
    App->>App: 解析 "GET / HTTP/1.1..." 🎉

每层的动作可以概括为三步:

  1. 检查:校验和是否正确?mac/ip/port 是否指向自己?
  2. 剥离:去掉本层的 Header(必要时 Tail 如 FCS)
  3. 移交:将剩余的 Payload 交给上层协议处理

各层 PDU 对照表

OSI 名称 PDU TCP/IP 对应 关键标识字段
数据 (Data) 报文段 应用层消息 —
段 (Segment) TCP Segment 传输层 PDU 源端口 + 目的端口
包 (Packet) IP Datagram 网络层 PDU 源 IP + 目的 IP + Protocol
帧 (Frame) Ethernet Frame 链路层 PDU 源 MAC + 目的 MAC + EtherType
比特流 (Bits) Bitstream 物理层信号 电信号 / 光脉冲

NAT 场景下的封装变化

NAT 路由器修改了中间层的地址:

发送端内部主机                    NAT 路由器                     外部 Web 服务器
┌──────────────────────┐     ┌──────────────────────┐     ┌──────────────────────┐
│  Src IP: 10.0.0.5:45678 │     │ SNAT: 改写 Src IP    │     │ Dst IP: 203.0.113.1:80  │
│  Dst IP: 203.0.113.1:80 │ →  │                      │ →   │                      │
│                      │     │ → Src IP: 8.8.8.8:45678 │     │ ← Src IP: 203.0.113.1:80  │
│                      │     │ → Dst IP: 203.0.113.1:80  │     │ → Src IP: 10.0.0.5:45678 │
└──────────────────────┘     └──────────────────────┘     └──────────────────────┘

注意:NAT 不触碰应用层载荷,只是在中途修改了 IP 和 TCP 端口。这也意味着 传输层的 Checksum 需要重新计算。

关联笔记