tcp 状态机

119 阅读8分钟

image.png

A connection progresses through a series of states during its lifetime.

The states are:

  • LISTEN,
  • SYN-SENT,
  • SYN-RECEIVED,
  • ESTABLISHED,
  • FIN-WAIT-1,
  • FIN-WAIT-2,
  • CLOSE-WAIT,
  • CLOSING,
  • LAST-ACK,
  • TIME-WAIT,
  • CLOSED.

CLOSED is fictional because it represents the state when there is no TCB, and therefore, no connection.

Briefly the meanings of the states are:

  • LISTEN: represents waiting for a connection request from any remote TCP and port.

  • SYN-SENT: represents waiting for a matching connection request after having sent a connection request.

  • SYN-RECEIVED: represents waiting for a confirming connection request acknowledgment after having both received and sent a connection request.

  • ESTABLISHED: represents an open connection, data received can be delivered to the user. The normal state for the data transfer phase of the connection.

  • FIN-WAIT-1: represents waiting for a connection termination request from the remote TCP, or an acknowledgment of the connection termination request previously sent.

  • FIN-WAIT-2: represents waiting for a connection termination request from the remote TCP.

  • CLOSE-WAIT: represents waiting for a connection termination request from the local user(app).

  • CLOSING: represents waiting for a connection termination request acknowledgment from the remote TCP.

  • LAST-ACK: represents waiting for an acknowledgment of the connection termination request previously sent to the remote TCP (which includes an acknowledgment of its connection termination request).

  • TIME-WAIT: represents waiting for enough time to pass to be sure the remote TCP received the acknowledgment of its connection termination request.

  • CLOSED: represents no connection state at all.

A TCP connection progresses from one state to another in response to events.

The events are the user calls, OPEN, SEND, RECEIVE, CLOSE, ABORT, and STATUS; the incoming segments, particularly those containing the SYN, ACK, RST and FIN flags; and timeouts.

内核 TCP 参数与 TCP 状态机

要分析内核中 TCP 相关参数的设计,需先锚定文档中 TCP 状态机的核心状态与转移逻辑(如连接建立的 LISTEN/SYN-SENT/SYN-RECEIVED、数据传输的 ESTABLISHED、连接关闭的 FIN-WAIT/TIME-WAIT 等),再对应参数的作用场景 —— 内核参数本质是对 “状态维持、状态转移触发条件、资源占用” 的精细化控制,最终平衡 TCP 连接的可用性、性能与资源开销

一、核心关联逻辑:TCP 状态机与内核参数的关系

文档明确 TCP 状态转移由三类事件驱动:

  1. 用户层操作(如OPEN主动 / 被动打开、CLOSE关闭);

  2. 网络报文触发(如 SYN/ACK/FIN/RST 段);

  3. 超时事件(如连接建立超时、TIME-WAIT 超时)。

内核 TCP 参数正是针对这三类事件,对 “状态存续时长、重试次数、队列容量、异常处理策略” 进行配置,避免状态异常堆积(如 TIME-WAIT 连接过多)、连接失败重试浪费资源、服务被洪水攻击打垮等问题。

二、分阶段解析内核 TCP 参数(对应文档状态)

阶段 1:连接建立阶段(LISTEN → SYN-SENT → SYN-RECEIVED → ESTABLISHED)

此阶段核心是 “快速建立有效连接,抵御无效请求(如 SYN 洪水),避免资源空置”,对应文档中LISTEN(被动等待请求)、SYN-SENT(主动发 SYN 后等待)、SYN-RECEIVED(收 SYN 后发 SYN+ACK 等待 ACK) 三个状态。

内核参数对应文档状态 / 转移含义与设计目的
tcp_max_syn_backlogLISTEN → SYN-RECEIVED(SYN 队列)定义LISTEN 状态下,服务器能暂存的 SYN 请求队列长度(即未完成三次握手的连接数)。目的:防止 SYN 洪水攻击导致队列溢出,避免合法请求被丢弃,平衡 “服务容量” 与 “内存占用”。
tcp_syn_retriesSYN-SENT(主动打开后等待)控制客户端在 SYN-SENT 状态下,重发 SYN 报文的次数(默认 5 次,总超时约 3 分钟)。目的:避免客户端因网络波动一直等待连接(无限重试浪费 CPU / 端口),同时保证弱网环境下的连接成功率。
tcp_synack_retriesSYN-RECEIVED(发 SYN+ACK 后等待)控制服务器在 SYN-RECEIVED 状态下,重发 SYN+ACK 报文的次数(默认 5 次)。目的:对应文档中 “SYN-RECEIVED 等待确认 ACK” 的逻辑,防止服务器因客户端未收到 SYN+ACK 而无限重试,释放无效的 SYN-RECEIVED 状态资源。
tcp_syncookiesLISTEN → SYN-RECEIVED(SYN 队列满时)开启后,当 SYN 队列满,服务器不丢弃 SYN 请求,而是生成 “Sync Cookie”(含连接信息的哈希值)放入 SYN+ACK 报文。目的:抵御 SYN 洪水攻击(攻击者无法伪造 Cookie 响应),保证 LISTEN 状态的服务可用性,避免 SYN-RECEIVED 状态堆积。
tcp_abort_on_overflowLISTEN(SYN 队列满时)当 SYN 队列满,服务器是否发送RST 报文给客户端(而非默认丢弃)。目的:对应文档中 “recv: RST” 的异常处理,让客户端快速感知 “连接失败”(而非一直重试超时),减少客户端资源浪费。
阶段 2:数据传输阶段(ESTABLISHED)

此阶段是 TCP 连接的核心(文档定义为 “可向用户交付数据的正常状态”),参数设计目标是 “保证连接存活、优化传输效率、避免僵尸连接”。

内核参数对应文档状态(ESTABLISHED)含义与设计目的
tcp_keepalive_timeESTABLISHED(无数据传输时)定义ESTABLISHED 状态下,无数据传输后多久触发 TCP 保活探测(默认 7200 秒,即 2 小时)。目的:检测 “僵尸连接”(如客户端崩溃未发 FIN),避免 ESTABLISHED 状态的无效连接长期占用服务器端口 / 内存。
tcp_keepalive_intvlESTABLISHED(保活探测)控制保活探测的重试间隔(默认 75 秒)。目的:若第一次探测无响应,后续每隔此时间重试,平衡 “快速检测死连接” 与 “减少网络探测开销”。
tcp_keepalive_probesESTABLISHED(保活探测)控制保活探测的总重试次数(默认 9 次)。目的:若多次探测无响应,服务器主动关闭连接(释放 ESTABLISHED 资源),避免无限探测浪费带宽。
tcp_window_scalingESTABLISHED(数据传输)开启 TCP 窗口缩放(RFC 1323),将 TCP 窗口大小从默认 65535 字节扩展到最大 1GB。目的:优化大带宽场景(如跨地域传输)的 ESTABLISHED 状态传输效率,避免 “窗口满导致的频繁等待 ACK”。
tcp_sackESTABLISHED(数据重传)开启 “选择性确认”(SACK),允许接收方告知发送方 “哪些数据段已丢失”,而非仅确认最后一个正确接收的段。目的:减少 ESTABLISHED 状态下的冗余重传(如仅重传丢失的小段),提升丢包场景下的传输效率。
阶段 3:连接关闭阶段(ESTABLISHED → FIN-WAIT-1/FIN-WAIT-2/CLOSE-WAIT → LAST-ACK → TIME-WAIT → CLOSED)

此阶段核心是 “安全释放连接,避免旧报文干扰新连接”,对应文档中主动关闭(FIN-WAIT-1/2、TIME-WAIT)、被动关闭(CLOSE-WAIT、LAST-ACK)、同时关闭(CLOSING) 等状态。

内核参数对应文档状态 / 转移含义与设计目的
tcp_fin_timeoutFIN-WAIT-2(主动关闭后等待 FIN)定义FIN-WAIT-2 状态下,服务器(主动关闭方)等待远程发 FIN 的超时时间(默认 60 秒)。目的:对应文档中 “FIN-WAIT-2 等待远程 TCP 终止请求” 的逻辑,若远程一直不发 FIN,超时后主动关闭连接,避免 FIN-WAIT-2 状态长期堆积(占用端口)。
tcp_time_wait_lenTIME-WAIT(等待 2MSL)定义TIME-WAIT 状态的存续时间(默认 60 秒,即 2 倍 MSL,MSL 为报文最大生存时间,通常 30 秒)。目的:文档明确 TIME-WAIT 是 “确保远程收到终止 ACK”,此参数保证:1. 旧连接的延迟报文(如 FIN/ACK)已消失,不干扰新连接;2. 远程未收到 ACK 时,本地仍能重发。
tcp_max_tw_bucketsTIME-WAIT(状态数量限制)定义系统能同时存在的TIME-WAIT 状态连接最大数量(默认 180000)。目的:TIME-WAIT 连接会占用端口(每个连接对应一个本地端口),若数量过多会耗尽端口资源(默认端口范围 65535),此参数限制后,内核会关闭旧的 TIME-WAIT 连接,保证新连接能分配端口。
tcp_tw_reuseTIME-WAIT(端口复用)允许TIME-WAIT 状态的端口被新的 TCP 连接复用(需满足 “新连接的四元组与旧连接不同” 或 “时间超过 1 秒”)。目的:缓解 TIME-WAIT 端口耗尽问题(如高并发短连接场景),在不影响新连接安全性的前提下提升端口利用率。
tcp_tw_recycleTIME-WAIT(快速回收)开启后,内核会快速回收来自同一 IP、同一端口的 TIME-WAIT 连接(需配合 tcp_timestamps 使用)。目的:进一步减少 TIME-WAIT 堆积,但因可能导致 NAT 网络下的连接异常(不同客户端通过同一 NAT IP 访问,会被误判为同一连接),现代内核已逐步弃用。
tcp_orphan_retriesFIN-WAIT-1/LAST-ACK(孤儿连接)控制孤儿连接(本地已关闭、远程未响应)在 FIN-WAIT-1/LAST-ACK 状态下的重发次数(默认 0 次,即直接超时)。目的:避免孤儿连接长期占用资源,快速释放 FIN-WAIT-1/LAST-ACK 状态的无效连接。

三、内核 TCP 参数设计的核心目标

从 TCP 状态机视角看,所有参数的设计均围绕三个核心矛盾展开,最终服务于 “TCP 连接的可靠性与资源高效利用”:

  1. 可靠性 vs 资源开销:如tcp_syn_retries通过有限重试保证弱网连接,同时避免无限重试浪费 CPU;tcp_time_wait_len通过 2MSL 等待保证报文不干扰,同时限制时长避免端口占用。

  2. 服务容量 vs 攻击抵御:如tcp_max_syn_backlog平衡 “接收更多 SYN 请求” 与 “抵御 SYN 洪水”,tcp_syncookies在队列满时仍能处理合法请求。

  3. 并发效率 vs 稳定性:如tcp_tw_reuse提升高并发短连接的端口利用率,tcp_keepalive_*避免僵尸连接占用资源,保证系统能处理更多有效连接。

综上,内核 TCP 参数是 TCP 状态机 “落地实现” 的关键配置 —— 通过精细化控制每个状态的 “存续规则” 与 “转移条件”,让 TCP 在复杂网络环境下既保证可靠性,又不浪费系统资源。