2. TCP协议基础与核心机制
TCP(Transmission Control Protocol,传输控制协议)是互联网协议栈中面向连接的、可靠的、基于字节流的传输层协议。理解TCP的头部结构、序列号机制、状态转换以及连接管理过程,是深入分析和调优Linux内核TCP拥塞控制的前提。本章将逐一拆解这些核心机制。
2.1 TCP头部结构解析
TCP头部固定部分为20字节,选项部分最多可扩展至60字节。下图展示了TCP头部的完整字段布局。
关键字段速查:
- 源/目的端口(16位): 标识通信的应用程序进程,与IP地址共同构成套接字(Socket)。
- 序列号(32位): 本报文段数据部分的第一个字节的序号,用于数据排序和去重。
- 确认号(32位): 期望收到的下一个字节的序号,表示之前的数据已成功接收。
- 标志位(6位): URG、ACK、PSH、RST、SYN、FIN,控制连接状态。
- 窗口大小(16位): 接收方通告的可用缓冲区大小,用于流量控制。
2.2 序列号与确认号
序列号(SEQ)和确认号(ACK)是TCP实现可靠传输的核心计数器。它们基于字节流编号,而非报文段编号。
| 概念 | 含义 | 示例 |
|---|---|---|
| 初始序列号(ISN) | 连接建立时随机选择的起始序号 | ISN = 1000 |
| 序列号(SEQ) | 当前报文段数据第一个字节的序号 | SEQ = 1000(数据长度100字节) |
| 确认号(ACK) | 期望收到的下一个字节序号,累积确认 | ACK = 1100(表示0~1099已收到) |
| 确认丢失 | 发送方未收到ACK,触发超时重传 | 超时时间RTO动态计算 |
调优视角: 序列号空间为32位,约4.3GB。在高速网络(如10Gbps+)中,序列号回绕(PAWS,Protection Against Wrapped Sequences)机制至关重要,Linux内核通过时间戳选项来检测回绕。
2.3 TCP状态转换图
TCP连接的生命周期由11种状态组成,状态转换由用户调用(如connect、close)和接收到的报文段(如SYN、FIN、ACK)驱动。下图展示了完整的TCP状态机。
常见陷阱: TIME_WAIT状态持续2MSL(Maximum Segment Lifetime,通常60秒),目的是确保最后一个ACK被对端接收,并防止旧连接报文干扰新连接。高并发短连接场景下,TIME_WAIT过多会耗尽端口资源,可通过调整
net.ipv4.tcp_tw_reuse 和 net.ipv4.tcp_tw_recycle(Linux 4.12+已移除)缓解。
2.4 三次握手与四次挥手
连接建立(三次握手)和连接释放(四次挥手)是TCP状态转换的具体体现。下面通过步骤列表和对比表格详细说明。
2.4.1 三次握手(连接建立)
- SYN(客户端→服务器): 客户端发送SYN报文段,初始序列号设为ISN_c(如1000),消耗一个序列号。客户端进入SYN_SENT状态。
- SYN+ACK(服务器→客户端): 服务器收到SYN,回复SYN+ACK报文段,确认号为ISN_c+1,自身初始序列号为ISN_s(如2000)。服务器进入SYN_RCVD状态。
- ACK(客户端→服务器): 客户端收到SYN+ACK,发送ACK报文段,确认号为ISN_s+1。客户端和服务器均进入ESTABLISHED状态。
2.4.2 四次挥手(连接释放)
- FIN(主动关闭方→被动关闭方): 主动关闭方发送FIN报文段,序列号为当前发送序号,进入FIN_WAIT_1状态。
- ACK(被动关闭方→主动关闭方): 被动关闭方收到FIN,回复ACK,确认号为FIN序号+1,进入CLOSE_WAIT状态。主动关闭方收到ACK后进入FIN_WAIT_2状态。
- FIN(被动关闭方→主动关闭方): 被动关闭方数据发送完毕,发送FIN报文段,进入LAST_ACK状态。
- ACK(主动关闭方→被动关闭方): 主动关闭方收到FIN,回复ACK,进入TIME_WAIT状态。被动关闭方收到ACK后进入CLOSED状态。
| 阶段 | 报文交换 | 状态变化(客户端) | 状态变化(服务器) |
|---|---|---|---|
| 三次握手 | SYN → SYN+ACK → ACK | CLOSED → SYN_SENT → ESTABLISHED | LISTEN → SYN_RCVD → ESTABLISHED |
| 四次挥手 | FIN → ACK → FIN → ACK | ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT → CLOSED | ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED |
内核调优关联:
- SYN Flood攻击防护: 通过
net.ipv4.tcp_syncookies启用SYN Cookie,避免半连接队列(SYN_RCVD状态)被耗尽。 - TCP_DEFER_ACCEPT: 服务器在三次握手完成后,延迟到收到实际数据时才唤醒应用,减少上下文切换。
- TCP_QUICKACK: 禁用延迟确认(Delayed ACK),适用于低延迟交互场景。
面试高频题: 为什么是三次握手而不是两次?核心原因是防止已失效的连接请求报文段突然又传到服务器,导致服务器误开连接。三次握手通过双方交换初始序列号并确认,确保双方都具有发送和接收能力。