Files
cs-note/hhs/NETWORK/04-传输层/01-TCP段结构与状态机.md
T
2026-05-24 11:42:38 +08:00

156 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [计算机网络, TCP, 状态机, 三次握手, 四次挥手]
create time: 2026-05-18 01:30
---
# TCP 段结构与状态机
## 概述
TCP(Transmission Control Protocol)是互联网最核心的可靠传输协议。理解其段结构和完整状态机,是排查线上网络问题的基本功。
## TCP 首部格式(32-bit fields)
```
┌─────────────┬─────────────┬───────────────────┐
│ Source Port │ Destination Port│ Sequence No │
│ 2 bytes │ 2 bytes │ 4 bytes │
├─────────────┼───────────────┤ │
│ Ack No │ Data Offset | Reserved│ECN│ CWR│ ACK │ PSH │ RST │ SYN │ FIN │
│ 4 bytes │ 4bits │ 3 bits │ │ │ │ │ │
├─────────────┴─────────────┴───────────────────┤
│ Window Size │
│ 2 bytes │
├───────────────────┬───────────────────────────┤
│ Checksum │ Urgent Pointer │
│ 2 bytes │ 2 bytes │
├───────────────────┴───────────────────────────┤
│ Options (variable) │
│ Max: 40 bytes │
└───────────────────────────────────────────────┘
Minimum header: 20 bytes
Maximum header: 60 bytes (with options)
```
### 关键字段详解
| 字段 | 大小 | 说明 |
|------|------|------|
| **Source/Dest Port** | 各 2B | 源端口和目的端口 |
| **Sequence Number** | 4B | 本报文第一个字节的序号(32 bit,约 4GB) |
| **Acknowledgment Number** | 4B | 期望收到的下一个字节序号(ACK=1 时有效) |
| **Data Offset** | 4 bit | 首部长度,单位 4 bytes(最小 5 = 20B,最大 F = 60B) |
| **Reserved** | 3 bit | 保留字段,必须为 0 |
| **ECN** | 2 bit | ECN-Echo + CWR:显式拥塞通知 |
| **URG** | 1 bit | 紧急指针有效 |
| **ACK** | 1 bit | 确认号有效(除首次 SYN 外几乎所有包都设 ACK=1) |
| **PSH** | 1 bit | 推送标志,告诉接收端立即提交应用层 |
| **RST** | 1 bit | 复位连接(异常关闭) |
| **SYN** | 1 bit | 同步序列号(建立连接) |
| **FIN** | 1 bit | 结束标志(优雅关闭) |
| **Window Size** | 2B | 接收窗口大小,流量控制基础 |
| **Checksum** | 2B | 覆盖首部 + 数据的 CRC |
| **Urgent Pointer** | 2B | URG=1 时偏移量,指示紧急数据位置 |
### 常用 TCP Options
| Option | 大小 | 说明 |
|--------|------|------|
| NOP | 1B | No Operation,用于填充对齐 |
| MSS | 4B | Maximum Segment Size,通常 1460(1500-MT-20IP) |
| Window Scale | 4B | 扩大窗口因子(2^x倍,最大 14 = 16384 倍) |
| SACK Perm / SACK | 可变 | Selective Acknowledgment,选择性确认 |
| Timestamps | 10B | TSval + TSecr,RTT 测量和防回绕 |
## TCP 状态机——完整图
```mermaid
stateDiagram-v2
[*] --> CLOSED
note right of CLOSED
TCP 不活跃状态
只有监听套接字在此
end note
CLOSED --> LISTEN: socket() + listen()
LISTEN --> SYN_RCVD: 收到 SYN (server only)
LISTEN --> ESTABLISHED: connect() + remote SYN-ACK (client side rare)
note right of SYN_SENT
client sent SYN
waiting for SYN-ACK
end note
SYN_RCVD --> ESTABLISHED: 3-Way Handshake Complete
SYN_SENT --> ESTABLISHED: Got SYN-ACK
ESTABLISHED --> CLOSE_WAIT: Application calls close()
ESTABLISHED --> FIN_WAIT_1: Remote sends FIN
FIN_WAIT_1 --> FIN_WAIT_2: Local ACK received
FIN_WAIT_1 --> CLOSING: Simultaneous close
FIN_WAIT_2 --> TIME_WAIT: Remote FIN received
CLOSING --> TIME_WAIT: Remote ACK received
CLOSE_WAIT --> LAST_ACK: Local application close
LAST_ACK --> CLOSED: Final ACK received
TIME_WAIT --> CLOSED: 2 * MSL timeout
note right of TIME_WAIT
Must wait 2*MSL
Ensures final ACK arrives
Prevents old duplicate packets
end note
note right of CLOSE_WAIT
Server side closing
Application must call close()
end note
```
### 所有 11 种状态一览
| # | 状态 | 触发条件 | 谁处于? |
|---|------|---------|---------|
| 1 | CLOSED | 初始/终止 | 双方初始状态 |
| 2 | LISTEN | `listen()` 系统调用 | 服务端 |
| 3 | SYN_SENT | `connect()` 发出 SYN | 客户端 |
| 4 | SYN_RCVD | 收到 SYN | 服务端 |
| 5 | ESTABLISHED | 三次握手完成 | 双方 |
| 6 | FIN_WAIT_1 | 本地调用 close() | 主动关闭方 |
| 7 | FIN_WAIT_2 | FIN_WAIT_1 的 ACK 到达 | 主动关闭方 |
| 8 | CLOSE_WAIT | 收到远程 FIN | **被动关闭方**(服务器!)|
| 9 | CLOSING | 同时关闭 | 极少见 |
| 10 | LAST_ACK | 本地发送最后一个 FIN | 被动关闭方 |
| 11 | TIME_WAIT | 发送完最后一个 ACK | 主动关闭方 |
> [!tip] 哪些状态是你最常看到的?
> - **ESTABLISHED**: 正常工作
> - **TIME_WAIT**: 高频短连接的服务端(如 nginx、API 网关)
> - **CLOSE_WAIT**: ⚠️ **应用 Bug!** 说明服务器收到了客户端的关闭请求但没调用 close()
### CLOSE_WAIT 堆积排查
```bash
# 查看 CLOSE_WAIT 数量
$ ss -tan state close-wait | wc -l
4521
# 是谁引起的?查进程
$ ss -tan state close-wait src :80
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
CLOSE-WAIT 0 0 10.0.0.1:80 203.0.113.5:45678 app=nginx(1234)
# 解决方案: 修复代码中未正确关闭的文件描述符/HTTP连接
```
## 关联笔记
- [[hhs/NETWORK/TCP三次握手与四次挥手]] — 详细解析握手/挥手过程
- [[hhs/NETWORK/TCP可靠传输机制]] — 序列号/确认号的深入讲解
- [[hhs/NETWORK/TCP拥塞控制]] — TCP 窗口的动态管理