156 lines
6.2 KiB
Markdown
156 lines
6.2 KiB
Markdown
---
|
||
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 窗口的动态管理
|