2. TCP协议基础与核心机制

TCP(Transmission Control Protocol,传输控制协议)是互联网协议栈中面向连接的、可靠的、基于字节流的传输层协议。理解TCP的头部结构、序列号机制、状态转换以及连接管理过程,是深入分析和调优Linux内核TCP拥塞控制的前提。本章将逐一拆解这些核心机制。

2.1 TCP头部结构解析

TCP头部固定部分为20字节,选项部分最多可扩展至60字节。下图展示了TCP头部的完整字段布局。

TCP头部结构 TCP头部结构(固定20字节 + 选项) 源端口(16位) 目的端口(16位) 序列号(32位) 确认号(32位) 数据偏移(4位) 保留(6位) 标志位(6位) 窗口大小(16位) 校验和(16位) 紧急指针(16位) 选项(可变长度,0~40字节) 数据偏移字段指示头部总长度(单位:4字节),最大60字节
关键字段速查:
  • 源/目的端口(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状态机。

TCP状态转换图 TCP状态转换图(核心路径) CLOSED LISTEN SYN_SENT SYN_RCVD ESTABLISHED FIN_WAIT_1 CLOSE_WAIT TIME_WAIT 被动打开 主动打开/SYN 收到SYN 收到SYN+ACK 收到ACK 主动关闭/FIN 收到FIN 收到FIN+ACK (后续进入LAST_ACK)
常见陷阱: 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 三次握手(连接建立)

  1. SYN(客户端→服务器): 客户端发送SYN报文段,初始序列号设为ISN_c(如1000),消耗一个序列号。客户端进入SYN_SENT状态。
  2. SYN+ACK(服务器→客户端): 服务器收到SYN,回复SYN+ACK报文段,确认号为ISN_c+1,自身初始序列号为ISN_s(如2000)。服务器进入SYN_RCVD状态。
  3. ACK(客户端→服务器): 客户端收到SYN+ACK,发送ACK报文段,确认号为ISN_s+1。客户端和服务器均进入ESTABLISHED状态。

2.4.2 四次挥手(连接释放)

  1. FIN(主动关闭方→被动关闭方): 主动关闭方发送FIN报文段,序列号为当前发送序号,进入FIN_WAIT_1状态。
  2. ACK(被动关闭方→主动关闭方): 被动关闭方收到FIN,回复ACK,确认号为FIN序号+1,进入CLOSE_WAIT状态。主动关闭方收到ACK后进入FIN_WAIT_2状态。
  3. FIN(被动关闭方→主动关闭方): 被动关闭方数据发送完毕,发送FIN报文段,进入LAST_ACK状态。
  4. 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),适用于低延迟交互场景。
面试高频题: 为什么是三次握手而不是两次?核心原因是防止已失效的连接请求报文段突然又传到服务器,导致服务器误开连接。三次握手通过双方交换初始序列号并确认,确保双方都具有发送和接收能力。