TCP 协议(TCP Protocol)
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的传输层协议。
什么是 TCP
TCP 是传输层协议,提供可靠的、面向连接的数据传输服务。
TCP 的特点
- 面向连接:通信前需要建立连接
- 可靠传输:保证数据正确到达
- 全双工通信:可以同时双向传输
- 流量控制:防止发送方发送过快
- 拥塞控制:防止网络拥塞
TCP 连接管理
三次握手(Three-Way Handshake)
目的:建立 TCP 连接
过程:
客户端 服务器
| |
|--- SYN (seq=x) ------------>|
| |
|<-- SYN-ACK (seq=y, ack=x+1) -|
| |
|--- ACK (ack=y+1) ---------->|
| |
|<===== 连接建立 =============>|
详细说明:
- 客户端发送 SYN:请求建立连接,序列号为 x
- 服务器发送 SYN-ACK:确认收到 SYN,同时发送自己的 SYN,序列号为 y,确认号为 x+1
- 客户端发送 ACK:确认收到服务器的 SYN,确认号为 y+1
为什么是三次握手?
- 确保双方都能发送和接收数据
- 防止旧的重复连接请求造成混乱
四次挥手(Four-Way Handshake)
目的:关闭 TCP 连接
过程:
客户端 服务器
| |
|--- FIN (seq=x) ------------>|
| |
|<-- ACK (ack=x+1) -----------|
| |
|<-- FIN (seq=y) --------------|
| |
|--- ACK (ack=y+1) ---------->|
| |
|<===== 连接关闭 =============>|
详细说明:
- 客户端发送 FIN:请求关闭连接
- 服务器发送 ACK:确认收到 FIN
- 服务器发送 FIN:服务器也准备关闭连接
- 客户端发送 ACK:确认收到服务器的 FIN
为什么是四次挥手?
- TCP 是全双工的,需要双方都关闭
- 服务器可能还有数据要发送,所以先确认,再发送 FIN
TCP 可靠性保证
1. 序列号和确认号
序列号(Sequence Number):标识每个字节的位置
确认号(Acknowledgment Number):期望收到的下一个字节的序列号
示例:
发送方发送:seq=100, len=50 (字节 100-149)
接收方确认:ack=150 (期望收到字节 150)
2. 确认机制(ACK)
工作原理:
- 接收方收到数据后,发送 ACK 确认
- 如果发送方未收到 ACK,会重传数据
3. 重传机制(Retransmission)
超时重传:
- 发送数据后启动定时器
- 如果超时未收到 ACK,重传数据
快速重传:
- 收到 3 个重复的 ACK,立即重传
- 比超时重传更快
TCP 流量控制
滑动窗口(Sliding Window)
目的:控制发送方的发送速度,防止接收方缓冲区溢出
工作原理:
- 接收方在 ACK 中告知可用窗口大小
- 发送方根据窗口大小调整发送速度
窗口大小:
可用窗口 = 接收窗口 - 已发送但未确认的数据
示例:
接收窗口:1000 字节
已发送未确认:300 字节
可用窗口:700 字节
TCP 拥塞控制
拥塞控制算法
TCP 使用多种算法控制拥塞:
1. 慢启动(Slow Start)
特点:
- 连接建立后,拥塞窗口(cwnd)从 1 开始
- 每收到一个 ACK,cwnd 翻倍
- 指数增长
过程:
cwnd = 1
收到 ACK → cwnd = 2
收到 ACK → cwnd = 4
收到 ACK → cwnd = 8
...
2. 拥塞避免(Congestion Avoidance)
特点:
- 达到慢启动阈值(ssthresh)后,进入拥塞避免
- 每收到一个 ACK,cwnd 增加 1
- 线性增长
3. 快速重传和快速恢复
快速重传:
- 收到 3 个重复 ACK,立即重传
- 不等待超时
快速恢复:
- 收到 3 个重复 ACK,进入快速恢复
- cwnd = ssthresh + 3
- 每收到重复 ACK,cwnd + 1
TCP 状态转换
TCP 状态
| 状态 | 说明 |
|---|---|
| CLOSED | 关闭状态 |
| LISTEN | 监听状态(服务器) |
| SYN_SENT | 已发送 SYN(客户端) |
| SYN_RECEIVED | 已收到 SYN(服务器) |
| ESTABLISHED | 连接已建立 |
| FIN_WAIT_1 | 已发送 FIN,等待 ACK |
| FIN_WAIT_2 | 已收到 ACK,等待 FIN |
| CLOSE_WAIT | 已收到 FIN,等待关闭 |
| LAST_ACK | 已发送 FIN,等待 ACK |
| TIME_WAIT | 等待 2MSL 后关闭 |
状态转换图
CLOSED
↓ (主动打开)
SYN_SENT → ESTABLISHED
↓ (被动打开)
LISTEN → SYN_RECEIVED → ESTABLISHED
↓ (主动关闭)
ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT → CLOSED
↓ (被动关闭)
ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED
TCP 头部结构
TCP 头部格式
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段说明:
- Source Port:源端口(16 位)
- Destination Port:目标端口(16 位)
- Sequence Number:序列号(32 位)
- Acknowledgment Number:确认号(32 位)
- Data Offset:数据偏移(4 位)
- Flags:控制标志(URG、ACK、PSH、RST、SYN、FIN)
- Window:窗口大小(16 位)
- Checksum:校验和(16 位)
TCP vs UDP
| 特性 | TCP | UDP |
|---|---|---|
| 连接 | 面向连接 | 无连接 |
| 可靠性 | 可靠 | 不可靠 |
| 速度 | 较慢 | 较快 |
| 头部大小 | 20 字节 | 8 字节 |
| 流量控制 | ✅ | ❌ |
| 拥塞控制 | ✅ | ❌ |
| 应用场景 | Web、邮件、文件传输 | DNS、视频、游戏 |
实际应用
查看 TCP 连接
# Linux/Mac
netstat -an | grep ESTABLISHED
# 或
ss -t
# 查看 TCP 状态
netstat -an | grep tcp抓包分析
# 使用 tcpdump
sudo tcpdump -i eth0 tcp
# 使用 Wireshark(图形界面)
# 过滤 TCP 包:tcp
# 查看三次握手:tcp.flags.syn == 1常见问题
1. 为什么 TCP 是可靠的?
- 序列号和确认号
- 超时重传
- 流量控制
- 拥塞控制
2. TIME_WAIT 状态的作用?
- 确保最后一个 ACK 能够到达
- 防止旧的重复连接请求造成混乱
- 等待时间:2MSL(Maximum Segment Lifetime)
3. TCP 如何保证数据顺序?
通过序列号,接收方可以按序列号重组数据。
总结
TCP 协议要点:
- 面向连接:三次握手建立连接,四次挥手关闭连接
- 可靠性:序列号、确认号、重传机制
- 流量控制:滑动窗口机制
- 拥塞控制:慢启动、拥塞避免、快速重传
- 状态管理:TCP 连接有多种状态
理解 TCP 协议是网络编程和网络问题排查的基础。
相关链接: