2.2.3 TCP协议(连接管理、可靠性、流控与拥塞控制)

TCP(Transmission Control Protocol)是面向连接、可靠传输、基于字节流的传输层协议,适用于需要顺序、完整交付的数据通信。其核心机制包含连接管理、可靠性保障、流量控制与拥塞控制。以下结合原理草图、命令示例、排错与练习。

原理草图:连接管理与状态流转

文章图片

连接管理
- 三次握手:SYN → SYN+ACK → ACK,确认双方初始序列号(ISN),建立连接。
- 四次挥手:FIN/ACK 分离,主动关闭方进入 TIME_WAIT,避免旧报文影响新连接。
- 半连接与全连接队列:SYN 进入半连接队列,握手完成进入全连接队列;backlogsomaxconn 共同影响。
- 常见状态:LISTEN、SYN_SENT、SYN_RECV、ESTABLISHED、FIN_WAIT1/2、CLOSE_WAIT、LAST_ACK、TIME_WAIT。

可靠性机制
- 序列号与确认号:每个字节有序列号,ACK 确认连续接收。
- 重传机制:RTO 超时重传与快速重传(3 个重复 ACK)。
- 校验和:检测传输中的位错误。
- 有序交付与去重:乱序缓存重组,重复段丢弃。

流量控制
- 滑动窗口:接收端通告窗口(rwnd)限制发送速率。
- 零窗口与探测:窗口为 0 时暂停发送,定期探测恢复。

拥塞控制
- 慢启动:cwnd 指数增长探测可用带宽。
- 拥塞避免:达到 ssthresh 后线性增长。
- 快速重传/恢复:减少丢包恢复时间。
- ECN(可选):显式拥塞通知辅助判断拥塞。

关键命令示例(连接状态、队列与重传)

# 1) 查看 TCP 连接与状态
ss -antp

# 2) 按状态统计连接数
ss -ant | awk 'NR>1 {state[$1]++} END {for (s in state) print s, state[s]}'

# 3) 查看监听队列与backlog(含半连接)
ss -lnt

# 4) 查看内核 TCP 关键参数
sysctl net.core.somaxconn
sysctl net.ipv4.tcp_max_syn_backlog
sysctl net.ipv4.tcp_fin_timeout
sysctl net.ipv4.tcp_tw_reuse

# 5) 临时调整参数(立即生效,重启失效)
sudo sysctl -w net.core.somaxconn=4096
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=8192

# 6) 抓包观察握手与挥手(替换网卡与端口)
sudo tcpdump -i eth0 'tcp port 80 and (tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-ack) != 0)' -n

示例:搭建一个本地 TCP 测试服务并观察连接

# 1) 启动一个简单 TCP 服务(占用 8080)
sudo nc -l -p 8080

# 2) 另开终端发起连接
nc 127.0.0.1 8080

# 3) 查看握手后的连接状态
ss -antp | grep 8080

# 4) 退出客户端,观察服务端的 CLOSE_WAIT / LAST_ACK
# 客户端退出后服务端等待应用关闭连接

排错与定位要点
- SYN_RECV 过多:半连接队列积压,检查 tcp_max_syn_backlog,并关注 SYN Flood。
- TIME_WAIT 堆积:短连接过多导致端口耗尽,检查应用连接复用与 tcp_fin_timeout
- CLOSE_WAIT 增多:应用未及时关闭 socket,需检查程序逻辑。
- 重传率升高:链路质量差或拥塞,结合 ss -i 与抓包确认。

# 查看单个连接的重传与窗口信息
ss -i dst 127.0.0.1 dport = :8080

练习
1. 用 nc 启动服务,分别在客户端正常退出与异常断开(强杀进程),观察服务端状态变化。
2. 设置 net.ipv4.tcp_fin_timeout 为 15,观察 TIME_WAIT 持续时间变化。
3. 通过 tc qdisc 模拟丢包(需 root),观察 ss -i 中的重传变化:

# 添加 5% 丢包(测试结束后记得删除)
sudo tc qdisc add dev eth0 root netem loss 5%
# 查看连接重传情况
ss -i dst 1.1.1.1
# 删除丢包规则
sudo tc qdisc del dev eth0 root