vault backup: 2026-05-27 00:12:00
This commit is contained in:
@@ -40,19 +40,19 @@ flowchart LR
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App as HTTP 应用
|
||||
participant TCP as TCP Socket
|
||||
participant IP as 网络层 IP
|
||||
participant ETH as 以太网驱动
|
||||
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() 返回 → 帧已发出 ✅
|
||||
App->>TCP: "write GET / HTTP/1.1..."
|
||||
Note over TCP: "分配 seq,ack, 连接已建立"
|
||||
TCP->>IP: "Segment, daddr=x.x.x.x, sport=1234, dport=80"
|
||||
Note over IP: "查路由表, 下一跳网关"
|
||||
IP->>ETH: "Packet, src_ip=192.168.1.100, dst_ip=93.184.216.34"
|
||||
Note over ETH: "ARP 解析, dst_mac=aabb.ccdd.eeff"
|
||||
ETH->>ETH: "拼接 srcMAC,dstMAC,EtherType,Payload,FCS"
|
||||
ETH-->>App: "sendto 返回, 帧已发出"
|
||||
```
|
||||
|
||||
### Ethernet II 帧完整结构
|
||||
@@ -69,22 +69,26 @@ Offset Size Field 说明
|
||||
|
||||
总长度范围:**64 ~ 1518 bytes**(不含 VLAN Tag;有 VLAN Tag 则上限 1522)。
|
||||
|
||||
> [!tip] 为什么有最小 64 字节的限制?
|
||||
> 以太网使用 CSMA/CD 检测冲突,发送方需要在发完帧之前检测到碰撞信号。64 字节是为了保证在最大网络直径内,信号能往返一次。如果 IP 包太小导致帧不够 64 字节,链路层会自动填充 **Padding** 补齐到最小长度。接收端根据 IP 头部的 "Total Length" 字段识别真实载荷边界,剥离多余的填充。
|
||||
|
||||
> [!note] MTU = 1500 是什么意思?
|
||||
> MTU(Maximum Transmission Unit)是链路层允许的最大 Payload 大小,即 IP 包的最大体积。超过会被分片(Fragmentation),但分片会降低性能且增加丢包风险——这也是现代应用层(如 TLS、gRPC)倾向于小包传输的原因。
|
||||
> MTU(Maximum Transmission Unit)是链路层允许的最大 Payload 大小,即 IP 包(头部 + 载荷)的最大体积。超过 1500 字节的 IP 包会被路由器**分片(Fragmentation)**——拆成多个小片段分别传输,接收端再重组。
|
||||
> 分片的代价:任何一个分片丢失都会导致整个包重传;每片都需要独立的 IP 头,浪费带宽。因此 TCP 在三次握手时会协商 **MSS**(Maximum Segment Size)来主动避分片,而 UDP 应用(如 DNS、QUIC)则通过程序层面控制载荷大小。更底层的 **PMTU Discovery** 机制还能动态探测路径上最小的 MTU。
|
||||
|
||||
## 接收端:逐层解封装
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant ETH as 网卡收到 Frame
|
||||
participant IP as 剥离以太网头
|
||||
participant TCP as 剥离 TCP 头
|
||||
participant App as 提取 HTTP 数据
|
||||
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..." 🎉
|
||||
ETH->>IP: "FCS 校验通过, EtherType=0x0800, 剥离以太网头"
|
||||
IP->>TCP: "IP Checksum 正确, Protocol=6 TCP, 剥离 IP 头"
|
||||
TCP->>App: "按 Sequence Number 重组, 剥离 TCP 头"
|
||||
App->>App: "解析 GET / HTTP/1.1..."
|
||||
```
|
||||
|
||||
每层的动作可以概括为三步:
|
||||
@@ -95,32 +99,88 @@ sequenceDiagram
|
||||
|
||||
## 各层 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 | 物理层信号 | 电信号 / 光脉冲 |
|
||||
| OSI 层 | PDU 名称 | TCP/IP 对应 | 关键标识字段 |
|
||||
|--------|---------|-------------|-------------|
|
||||
| 应用层 | 消息 (Message) | 应用层数据 | HTTP 请求行、DNS 报文等 |
|
||||
| 传输层 | 段/数据报 (Segment / Datagram) | 传输层 PDU | 源端口 + 目的端口 |
|
||||
| 网络层 | 包 (Packet / Datagram) | 网络层 PDU | 源 IP + 目的 IP + Protocol |
|
||||
| 链路层 | 帧 (Frame) | 链路层 PDU | 源 MAC + 目的 MAC + EtherType |
|
||||
| 物理层 | 比特流 (Bits) | 物理层信号 | 电信号 / 光脉冲 / 无线电波 |
|
||||
|
||||
> [!QUESTION] TCP 叫 Segment,UDP 叫什么?
|
||||
> UDP 的 PDU 通常叫 **Datagram**(数据报),因为它不建立连接、不做分段重组,每个数据报独立发送。所以同一层可以有不同的 PDU 名称,取决于使用的传输协议。
|
||||
|
||||
## 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 │
|
||||
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Host as "内部主机"
|
||||
participant NAT as "NAT 路由器"
|
||||
participant Server as "外部服务器"
|
||||
|
||||
Host->>NAT: "Src=10.0.0.5:45678 Dst=203.0.113.1:80"
|
||||
Note over NAT: "SNAT 改写源地址"
|
||||
NAT->>Server: "Src=8.8.8.8:45678 Dst=203.0.113.1:80"
|
||||
Server->>NAT: "Src=203.0.113.1:80 Dst=8.8.8.8:45678"
|
||||
Note over NAT: "查 NAT 表, 反向翻译"
|
||||
NAT->>Host: "Src=203.0.113.1:80 Dst=10.0.0.5:45678"
|
||||
```
|
||||
|
||||
注意:NAT 不触碰应用层载荷,只是在中途修改了 IP 和 TCP 端口。这也意味着 **传输层的 Checksum 需要重新计算**。
|
||||
NAT **不触碰应用层载荷**,只修改 IP 头和 TCP/UDP 端口。但这也意味着**传输层的 Checksum 需要重新计算**,因为 TCP/UDP 的校验和覆盖了伪首部(Pseudo Header)中的源/目的 IP 地址。
|
||||
|
||||
## TCP vs UDP:封装有什么不同?
|
||||
|
||||
两者都在传输层,但封装风格截然不同:
|
||||
|
||||
| 对比项 | TCP | UDP |
|
||||
|--------|-----|-----|
|
||||
| 首部大小 | 最小 20 字节,最大 60 字节(含 Options) | 固定 8 字节 |
|
||||
| 连接状态 | 三次握手建连接,携带 seq/ack 等状态 | 无连接,每个数据报独立 |
|
||||
| 分段重组 | 传输层自动分段和重组 | 不分段,超过 MTU 则由 IP 层分片 |
|
||||
| 校验和 | 强制(IPv4/IPv6) | IPv4 可选,IPv6 强制 |
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph "TCP Segment"
|
||||
A["TCP Header 20-60B<br/>SrcPort DstPort Seq Ack Flags..."] --> B["Payload"]
|
||||
end
|
||||
subgraph "UDP Datagram"
|
||||
C["UDP Header 8B<br/>SrcPort DstPort Len Chksum"] --> D["Payload"]
|
||||
end
|
||||
|
||||
style A fill:#FFD700
|
||||
style C fill:#FFA07A
|
||||
```
|
||||
|
||||
> [!QUESTION] UDP 头只有 8 字节,是不是"更好"?
|
||||
> 更小的头部确实开销更低,但你失去的是可靠传输、流量控制、拥塞控制等保障。选择哪个取决于业务场景:文件传输用 TCP,游戏/视频/QUIC 用 UDP + 应用层自建可靠性。
|
||||
|
||||
## TLS 封装:在哪一层"套娃"?
|
||||
|
||||
TLS(Transport Layer Security)常被认为是"应用层协议",但它实际上在 **OSI 第 5-6 层(会话/表示层)** 工作,夹在应用层和传输层之间:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph "HTTPS = HTTP + TLS + TCP"
|
||||
H["HTTP 报文"] --> T["TLS 加密<br/>+ TLS Record Header 5B"]
|
||||
T --> C["TCP Segment"]
|
||||
C --> I["IP Packet"]
|
||||
end
|
||||
|
||||
style H fill:#DDA0DD
|
||||
style T fill:#FF6347
|
||||
style C fill:#FFD700
|
||||
style I fill:#87CEEB
|
||||
```
|
||||
|
||||
关键点:TLS Record 协议会在 HTTP 载荷前添加 **5 字节的 Record Header**(ContentType + Version + Length),然后整个 TLS Record 作为 TCP 的 Payload 继续向下封装。所以 HTTPS 比 HTTP 多了 TLS 的封装开销(握手阶段更大,数据阶段约 ~40 字节 overhead)。
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[hhs/NETWORK/OSI与TCP-IP模型对比]] — 分层模型的起源与对比
|
||||
- [[hhs/NETWORK/IPv4协议详解]] — IP 包的详细格式
|
||||
- [[hhs/NETWORK/TCP状态机详解]] — TCP 段的结构与状态管理
|
||||
- [[hhs/NETWORK/01-基础概念/01-OSI与TCP-IP模型对比]] — 分层模型的起源与对比
|
||||
- [[hhs/NETWORK/03-网络层/01-IPv4首部与分段重组]] — IP 包的详细格式与分片机制
|
||||
- [[hhs/NETWORK/04-传输层/01-TCP段结构与状态机]] — TCP 段的结构与状态管理
|
||||
- [[hhs/NETWORK/04-传输层/06-UDP协议与SCTP]] — UDP 的无连接封装特点
|
||||
- [[hhs/NETWORK/03-网络层/08-NAT原理与应用]] — NAT 的详细原理与配置
|
||||
|
||||
Reference in New Issue
Block a user