vault backup: 2026-05-17 22:27:07

This commit is contained in:
hhs
2026-05-17 22:27:07 +08:00
parent 64e34e6871
commit bbea71f62b
45 changed files with 8983 additions and 0 deletions
@@ -0,0 +1,140 @@
---
tags: [计算机网络, OSI模型, TCP/IP, 网络分层]
create time: 2026-05-17 22:10
---
# OSI 七层 vs TCP/IP 四层模型
## 概述
OSI(Open Systems Interconnection)和 TCP/IP 是理解计算机网络的两种经典分层模型。OSI 提供了一套理论化的参考框架,而 TCP/IP 则是实际运行在因特网上的协议栈。理解两者的映射关系,有助于我们在设计系统和排查问题时建立正确的抽象层次。
> [!QUESTION] 为什么现实用五层模型而不是 OSI?
> OSI 的七层理论很完美,但实现起来复杂到几乎不可能。TCP/IP 只有四层,又太粗。于是教学上采用折中的「五层模型」:把 OSI 的应用/表示/会话三层合并为应用层,保留传输层、网络层、链路层、物理层——刚好够表达所有关键概念。
## OSI 七层模型
### 分层结构
| 层级 | 名称 | PDU(协议数据单元) | 核心职责 |
|------|------|-----|---------|
| 7 | 应用层 | 数据(Data) | 为用户提供网络服务接口(HTTP、FTP、SMTP) |
| 6 | 表示层 | 数据 | 数据格式转换、加密解密、压缩解压 |
| 5 | 会话层 | 数据 | 建立/维护/终止会话(会话令牌、检查点) |
| 4 | 传输层 | 段(Segment) | 端到端可靠传输、流量控制、差错控制 |
| 3 | 网络层 | 包(Packet) | 路由选择、逻辑寻址(IP 地址) |
| 2 | 数据链路层 | 帧(Frame) | 物理寻址(MAC)、相邻节点间的帧传输 |
| 1 | 物理层 | 比特(Bit) | 电气特性、机械接口、光电信号转换 |
```mermaid
graph BT
subgraph "传输中封装"
D["应用层 Data"] --> L6["表示层: 加密+压缩"]
L6 --> L5["会话层: 建立/维护/结束会话"]
L5 --> S["传输层 Segment"]
S --> P["网络层 Packet"]
P --> F["链路层 Frame"]
F --> B["物理层 Bitstream"]
end
style D fill:#DDA0DD
style S fill:#FFD700
style F fill:#98FB98
style B fill:#B0C4DE
```
### 每层经典协议对照表
| 层 | 协议 | 作用场景 |
|----|------|---------|
| 应用层 | HTTP, DNS, SMTP, FTP, SSH, WebSocket | 应用间通信 |
| 表示层 | TLS/SSL, JPEG, MPEG, ASN.1 | 数据格式化与加密 |
| 会话层 | NetBIOS, RTP, SIP | 多路复用与同步 |
| 传输层 | TCP, UDP, SCTP | 端到端数据传输 |
| 网络层 | IP, ICMP, IGMP, ARP* | 跨网段路由转发 |
| 链路层 | Ethernet, Wi-Fi (802.11), VLAN, PPP | 相邻设备帧传输 |
| 物理层 | USB, RS-232, 光纤, Cat6 网线 | 物理信号传输 |
> [!note] ARP 到底在第几层?
> ARP 将 IP 地址解析为 MAC 地址,跨越了网络层和链路层的边界。OSI 将其放在**网络层下方、链路层上方**的"夹层"位置。现代观点常把它视为网络层的一部分。
## TCP/IP 四层模型
### 分层结构
| 层级 | 对应 OSI | 核心协议 | 核心职责 |
|------|----------|---------|---------|
| 应用层 | 7+6+5 层合并 | HTTP, DNS, SMTP, SSH | 面向应用的协议栈 |
| 传输层 | 4 层 | TCP, UDP | 端到端连接管理 |
| 网络层 | 3 层 | IP, ICMP, ARP | 分组路由与寻址 |
| 网络接口层 | 2+1 层合并 | Ethernet, Wi-Fi | 帧传输与物理介质 |
### 为何 OSI 没赢下标准之战
```mermaid
flowchart LR
A["OSI 七层模型<br/>ISO 标准"] --> B{谁先落地?}
B -->|"1970s 末"| C["TCP/IP 已部署在 ARPANET"]
B -->|"1980s 后"| D["OSI 标准太多太复杂"]
C --> E["事实标准 ✅"]
D --> E
style E fill:#98FB98,color:#000
```
- **先发优势**:ARPANET / Internet 先用上了 TCP/IP,基础设施已经建成
- **简单粗暴**:TCP/IP 只关心能不能跑通,不搞复杂的标准化流程
- **开源免费**:Berkeley BSD Unix 内嵌 TCP/IP 协议栈,免费分发
- **OSI 的反面教材**:层层审批导致协议膨胀(X.400 邮件、X.25 分组交换),开发者根本懒得用
## 五层教学模型
这是教材中最常用的模型,取两者精华:
```mermaid
flowchart TD
A["应用层 — Application<br/>HTTP DNS SMTP SSH FTP SMTP POP3 IMAP WebSocket"] --> T["传输层 — Transport<br/>TCP UDP SCTP"]
T --> N["网络层 — Internet<br/>IP IPv6 ICMP ARP NAT"]
N --> D["链路层 — Link<br/>Ethernet Wi-Fi 802.11 VLAN HDLC PPP"]
D --> P["物理层 — Physical<br/>双绞线 光纤 无线电 IEEE 802.15"]
style A fill:#DDA0DD
style T fill:#FFD700
style N fill:#87CEEB
style D fill:#98FB98
style P fill:#B0C4DE
```
## 数据包逐层穿越过程
以你发送一封电子邮件为例:
```mermaid
sequenceDiagram
participant App as 你的邮件客户端
participant T as TCP层
participant I as IP层
participant L as 以太网层
participant Router as 路由器
participant R as 接收方
App->>T: SMTP 邮件内容 (Data)
T->>T: 加 TCP 首部 (Header + Data → Segment)
T->>I: 传递 Segment
I->>I: 加 IP 首部 (Header + Segment → Packet)
I->>L: 传递 Packet
L->>L: 加以太网帧头帧尾 (Header + Packet + FCS → Frame)
L->>Router: 通过网线发送 Frame
Router->>Router: 拆帧 → 查路由表 → 重新封帧
Router->>R: 转发给接收方
R->>L: 解包 → IP层校验 → TCP重组 → 提取 SMTP
R->>App: 邮件到达收件箱
```
> [!tip] 封装 = 套娃;解封装 = 剥壳
> 每一层只知道自己那一层的 header 是什么格式,对其他层的内容一无所知。这就是**层间透明**原则。
## 关联笔记
- [[hhs/NETWORK/02-以太网帧结构]] — 链路层帧的详细结构
- [[hhs/NETWORK/03-IPv4协议详解]] — 网络层 IP 数据包格式
- [[hhs/NETWORK/04-TCP状态机详解]] — 传输层 TCP 连接管理
- [[hhs/NETWORK/05-HTTP请求响应]] — 应用层协议细节
@@ -0,0 +1,126 @@
---
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 |
```mermaid
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
```
## 发送端:逐层封装
```mermaid
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)倾向于小包传输的原因。
## 接收端:逐层解封装
```mermaid
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 需要重新计算**。
## 关联笔记
- [[hhs/NETWORK/OSI与TCP-IP模型对比]] — 分层模型的起源与对比
- [[hhs/NETWORK/IPv4协议详解]] — IP 包的详细格式
- [[hhs/NETWORK/TCP状态机详解]] — TCP 段的结构与状态管理
@@ -0,0 +1,169 @@
---
tags: [计算机网络, MAC地址, IP地址, 端口号]
create time: 2026-05-17 22:30
---
# 寻址体系:MAC / IP / Port
## 概述
网络中的每个端点需要三层地址才能精确定位到一个进程:**MAC 地址**(物理层/链路层)定位到哪台设备、**IP 地址**(网络层)定位到哪个子网、**端口号**(传输层)定位到哪个进程。三层地址组合起来,就是经典的 `ip:port` 定位公式。
> [!QUESTION] 为什么需要三种地址?一层不够吗?
> 每种地址解决不同尺度的问题。MAC 在同一个广播域内有效,但路由器不转发广播——跨网段必须用 IP 路由。IP 能到达目标主机,但不区分进程——同一台服务器可能跑着 Web、数据库、邮件等多个服务,所以需要端口来分发。
## 一、MAC 地址(48 位)
### 基本结构
```
前 3 字节 后 3 字节
───────────── ─────────────
OUI (厂商编号) NIC 序列号
由 IEEE 分配 由厂商自定
```
示例:`aabb.ccdd.eeff` = `AA:BB:CC:DD:EE:FF`
- 前三个字节 `AA:BB:CC` → OUI,代表厂商
- 后三个字节 `DD:EE:FF` → 设备唯一序列
### MAC 地址类型
| 类型 | 格式 | 含义 |
|------|------|------|
| 单播 | LSB=0 | 发给单个设备 |
| 广播 | `ff:ff:ff:ff:ff:ff` | 发给局域网内所有设备 |
| 组播 | LSB=1 | 发给一组设备 |
### ARP 地址解析
当知道一个主机的 **IP 地址** 时,需要通过 ARP 协议找到它的 **MAC 地址**。
```mermaid
sequenceDiagram
participant Src as 源主机<br/>192.168.1.10/?.mac
participant Bcast as 局域网广播
participant Dst as 目标主机<br/>192.168.1.20/aa:bb:cc:11:22:33
participant Cache as 源主机 ARP 缓存
Src->>Bcast: ARP Request "192.168.1.20 是谁?→ ff:ff:ff:ff:ff:ff"
Dst-->>Src: ARP Reply "我是!MAC = aa:bb:cc:11:22:33"
Src->>Cache: 写入缓存条目 (TTL ≈ 15~30 分钟)
Note over Src,Dst: 之后的通信直接用此 MAC,不再发 ARP
```
### ARP 缓存查看与管理
```bash
# Linux
$ ip neigh show # 等价于 arp -n
192.168.1.20 dev eth0 lladdr aa:bb:cc:dd:ee:ff STALE
$ ip neigh del 192.168.1.20 dev eth0 # 删除缓存条目
# macOS / Windows
$ arp -a
```
## 二、IP 地址(IPv4 32 位 / IPv6 128 位)
### IPv4 地址结构
```
版本(4 bits) IHL(4 bits) DSCP(8 bits) Total Length(16 bits)
...
Identification(16 bits) | DF/MF | Fragment Offset(13 bits)
TTL(8 bits) | Protocol(8 bits) | Header Checksum(16 bits)
Source Address(32 bits)
Destination Address(32 bits)
Options (可选)...
```
### IPv4 vs IPv6
| 特性 | IPv4 | IPv6 |
|------|------|------|
| 地址长度 | 32 bit (4 字节) | 128 bit (16 字节) |
| 地址数量 | ~43 亿 (2³²) | ~3.4×10³⁸ (2¹²⁸) |
| 表示法 | `192.168.1.1` | `2001:0db8::1` |
| 首部固定长度 | 20 bytes(可变选项更长) | 40 bytes(固定) |
| Checksum | ✅ 有 | ❌ 无(依赖上层校验) |
| NAT | 广泛使用(缓解地址耗尽) | 不需要(地址充足) |
| SLAAC | — | 支持无状态自动配置 |
| 组播 | 有限支持 | 原生支持 |
### IP 地址分类(历史)
| 类别 | 首字节范围 | 默认掩码 | 可用主机数 | 用途 |
|------|-----------|---------|-----------|------|
| A | 1–126 | /8 | 16,777,214 | 大型组织 |
| B | 128–191 | /16 | 65,534 | 中型组织 |
| C | 192–223 | /24 | 254 | 小型网络 |
| D | 224–239 | — | — | 组播 |
| E | 240–255 | — | — | 保留 |
> [!warning] CIDR 已淘汰分类编址
> 现代网络全部使用 **CIDR(Classless Inter-Domain Routing)** 无类编址,子网掩码可以是任意位数(如 /23、/27)。
## 三、端口号(16 位)
### 端口范围
| 范围 | 名称 | 说明 |
|------|------|------|
| 0–1023 | 熟知端口 (Well-Known) | 预分配给标准服务(HTTP:80, HTTPS:443, SSH:22, DNS:53) |
| 1024–49151 | 注册端口 (Registered) | 申请注册的商业软件 |
| 49152–65535 | 动态端口 (Ephemeral) | 客户端临时分配,用完即释放 |
### 服务端 vs 客户端端口
```mermaid
flowchart LR
Client["客户端 192.168.1.100:54321"] -->|"SYN"| Server["服务端 10.0.0.1:80"]
Server -->|"SYN-ACK"| Client
Client -->|"ACK"| Server
style Client fill:#DDA0DD,color:#000
style Server fill:#98FB98,color:#000
```
- **服务端端口**:固定且知名(如 80),告诉客户端"我在哪"
- **客户端端口**:操作系统动态分配(49152–65535),保证连接的唯一标识 `(src_ip, src_port, dst_ip, dst_port)`
### 常见端口速查
| 端口 | 协议 | 服务 |
|------|------|------|
| 21 | FTP | 文件传输控制 |
| 22 | SSH | 安全远程登录 |
| 25 | SMTP | 邮件发送 |
| 53 | DNS | 域名解析 |
| 80 | HTTP | Web 网站 |
| 443 | HTTPS | 加密 Web |
| 993 | IMAPS | 加密邮件收取 |
| 3306 | MySQL | 数据库 |
| 5432 | PostgreSQL | 数据库 |
| 6379 | Redis | 缓存 |
| 8080 | HTTP Alt | Web 备用端口 |
## 四、完整寻址链:从请求到进程
```mermaid
flowchart TD
S["你在浏览器输入 example.com"] -->|"DNS 查询"| A["DNS 返回 93.184.216.34"]
A -->|"TCP 三次握手"| B["建立 TCP 连接<br/>src:192.168.1.100:54321 → dst:93.184.216.34:80"]
B -->|"以太网帧头"| C["Dst MAC: router的出口MAC<br/>Src MAC: 本机MAC"]
C -->|"ARP缓存"| D["如果没缓存,先发ARP请求"]
D -->|"发送 HTTP GET"| E["Web 服务器的 PID 1234<br/>nginx worker 进程读取数据"]
style S fill:#DDA0DD,color:#000
style E fill:#98FB98,color:#000
```
**结论:** 三层地址缺一不可——没有 IP 找不到机器,没有 MAC 连不上网线,没有端口不知道该交给哪个进程。
## 关联笔记
- [[hhs/NETWORK/OSI与TCP-IP模型对比]] — 三层地址对应 OSI 的不同层级
- [[hhs/NETWORK/IPv4协议详解]] — IP 地址的详细编码与 CIDR 计算
- [[hhs/NETWORK/TCP状态机详解]] — 四元组如何唯一标识 TCP 连接
@@ -0,0 +1,165 @@
---
tags: [计算机网络, 带宽, 延迟, RTT, 吞吐量, BDP]
create time: 2026-05-17 22:40
---
# 带宽、延迟、RTT、吞吐量
## 概述
理解网络性能的核心指标,是优化应用的前提。带宽决定"管道有多粗",延迟决定"跑一程要多久",RTT 是往返一次的时间,而吞吐量是实际能搬多少数据。它们之间的关系经常影响系统架构设计。
## 核心定义
### 带宽(Bandwidth)
单位时间内能传输的**最大比特数**,通常用 bps(bits per second)表示:
```
1 Gbps = 10⁹ bits/s = 125 MB/s(注意:bit vs Byte)
```
| 链路类型 | 理论带宽 | 实际可用 |
|----------|---------|---------|
| 千兆以太网 (GbE) | 1 Gbps | ~940 Mbps(协议开销) |
| Wi-Fi 6 (802.11ax) | 9.6 Gbps | ~1.2–2 Gbps(理论峰值) |
| SATA III | 6 Gbps | 600 MB/s 实际 |
| PCIe 4.0 x16 | 32 Gbps | ~3.9 GB/s |
> [!tip] bit vs Byte:记住除 8
> 运营商说的 "100M 宽带" 是 **100 Mbps**。换算成下载速度约 `100 ÷ 8 ≈ 12.5 MB/s`。
### 延迟(Latency / Propagation Delay)
信号从发送端传播到接收端所需的时间,仅取决于**物理距离和介质光速**:
$$\text{Prop. Delay} = \frac{\text{Distance}}{v}$$
其中 $v$ 是传播速度。光纤中光速约为 $2 \times 10^8$ m/s(真空中光速的 2/3)。
| 场景 | 典型延迟 |
|------|---------|
| 同机房内 | 0.1–1 ms |
| 同城(同一城市数据中心) | 1–5 ms |
| 跨省(国内) | 20–40 ms |
| 跨洋(中美) | 80–150 ms |
| 卫星轨道(LEO) | 20–40 ms |
| TCP 握手 + TLS 1.3 | 1~2 RTT(额外 RTT × 加密计算时间) |
### RTT(Round-Trip Time)
从发送方发出数据包到收到确认应答的总时间。**RTT = 2 × 单向延迟 + 排队处理时间 + 传输时间**。
```mermaid
flowchart LR
A["t=0ms: 发送 SYN"] -->|"传播+路由器处理"| B["t=5ms: 到达服务端"]
B -->|"处理+准备响应"| C["t=5.1ms: 服务端回发 SYN-ACK"]
C -->|"传播+路由器处理"| D["t=10.2ms: 客户端收到 → RTT = 10.2ms"]
style A fill:#DDA0DD,color:#000
style D fill:#98FB98,color:#000
```
### 吞吐量(Throughput)
单位时间内**实际成功传输的数据量**,受限于最窄环节:
$$\text{Throughput} = \min(\text{带宽}, \text{拥塞窗口限制}, \text{应用处理能力})$$
实际吞吐量永远 ≤ 带宽。常见瓶颈:
```mermaid
flowchart LR
A["磁盘IO<br/>可能 < 网卡"] --> B["TCP收发缓冲区"]
B --> C["网络带宽"]
C --> D["对端带宽"]
D --> E["对端CPU/应用"]
F["中间路由拥塞"] -.-> C
G["丢包重传"] -.-> C
style C fill:#FFD700,color:#000
style F fill:#FF6B6B,color:#fff
style G fill:#FF6B6B,color:#fff
```
> [!question] 为什么我的千兆网卡只跑到 100MB/s?
> 因为千兆以太网理论上限是 `1Gbps ÷ 8 = 125MB/s`,去掉以太网帧头、IP 头、TCP 头等协议开销后,纯 Payload 大约 **94 MB/s**。如果还用了 HTTPS/TLS,CPU 加解密还会进一步限制吞吐量。
## 带宽时延积(BDP)
**BDP(Bandwidth-Delay Product)** 定义了链路上"在途"数据的最大量——这是维持满带宽所需的发送缓冲大小:
$$\text{BDP} = \text{Bandwidth} \times \text{RTT}$$
### 实际意义
假设带宽 1 Gbps,RTT = 100 ms:
$$\text{BDP} = 10^9 \text{ bps} \times 0.1s = 10^8 \text{ bits} = 12.5 \text{ MB}$$
这意味着:
- TCP 发送窗口至少要有 **12.5 MB**,才能填满这条管道
- 如果窗口太小,TCP 会频繁停下来等 ACK,吞吐量上不去
- 这就是 Linux 的 `net.core.rmem_max` / `wmem_max` 要调大的原因
```mermaid
flowchart TD
Pipe["管道: 1Gbps, RTT=100ms<br/>BDP = 12.5MB"]
Small["发送窗口 1MB ❌<br/>只能填 8% 管道 → 吞吐量 ≈ 80Mbps"]
Big["发送窗口 25MB ✅<br/>填满管道 → 吞吐量 ≈ 1Gbps"]
Pipe --> Small
Pipe --> Big
style Small fill:#FF6B6B,color:#fff
style Big fill:#98FB98,color:#000
```
### 各场景 BDP 速查
| 链路 | 带宽 | RTT | BDP |
|------|------|-----|-----|
| 局域网 | 1 Gbps | 0.5 ms | 62.5 KB |
| 同机房 | 10 Gbps | 1 ms | 1.25 MB |
| 同省 | 1 Gbps | 20 ms | 2.5 MB |
| 跨洋 | 100 Mbps | 150 ms | 1.875 MB |
## 延迟 vs 带宽的典型对比
| 场景 | 带宽瓶颈还是延迟瓶颈? | 说明 |
|------|---------------------|------|
| 大文件传输 | 带宽 | 传输时间长,RTT 占比小 |
| 小请求/高频交互(RPC) | 延迟 | 每个请求 2~3 RTT,带宽几乎不占 |
| 视频流 | 带宽 | 持续大量数据传输 |
| DNS 查询 | 延迟 | 单次查询仅几十字节 |
| Web 首屏加载 | 两者兼有 | TCP+TLS握手(延迟)+ HTML/CSS/JS 下载(带宽) |
## Go 中的实践示例
```go
// 设置 TCP 连接保持活跃,定期检测死链接
tcp := net.ListenConfig{
Control: func(network, address string, c syscall.RawConn) error {
return c.Control(func() {
// 开启 keepalive,每 30s 探测一次
syscall.SetsockoptInt(int(c.Fd()), syscall.SOL_SOCKET,
syscall.SO_KEEPALIVE, 1)
})
},
}
// HTTP Transport 的连接池配置
transport := &http.Transport{
MaxIdleConns: 100, // 最多空闲连接数
MaxIdleConnsPerHost: 10, // 每个 host 最多 10 个空闲
IdleConnTimeout: 90 * time.Second, // 空闲超时释放
}
```
## 关联笔记
- [[hhs/NETWORK/OSI与TCP-IP模型对比]] — 网络分层中各层的角色
- [[hhs/NETWORK/TCP状态机详解]] — TCP 的拥塞控制直接影响吞吐量
- [[hhs/NETWORK/TCP内核参数调优]] — BDP 对应内核参数 rmem/wmem