6.2 KiB
6.2 KiB
tags, create time
| tags | 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 状态机——完整图
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 堆积排查
# 查看 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 窗口的动态管理