面试高频考点:深入解析 TCP 三次握手与四次挥手原理
TCP 协议是互联网通信的核心基础,其可靠性机制通过三次握手建立连接、四次挥手释放连接来实现。在技术面试中,这部分内容属于必考的基础题,往往也是区分候选人对底层网络理解深度的关键。很多开发者虽然知道流程,但在面对状态变迁、队列机制及异常处理时容易回答不完整。
TCP 协议通过三次握手建立连接以确保可靠性,通过四次挥手释放连接以支持半关闭模式。本文详细阐述了握手与挥手的状态变迁、序列号同步机制、半连接队列与全连接队列的作用,以及 SYN 攻击原理与防御策略。同时补充了 TIME_WAIT 状态的成因、MSL 的意义及 Linux 内核相关调优参数,帮助开发者全面掌握网络编程核心知识,应对技术面试中的底层原理问题。

TCP 协议是互联网通信的核心基础,其可靠性机制通过三次握手建立连接、四次挥手释放连接来实现。在技术面试中,这部分内容属于必考的基础题,往往也是区分候选人对底层网络理解深度的关键。很多开发者虽然知道流程,但在面对状态变迁、队列机制及异常处理时容易回答不完整。
本文将系统梳理 TCP 连接的建立与断开过程,涵盖状态机变化、序列号同步、半连接队列机制、SYN 攻击防御以及 TIME_WAIT 状态的优化策略,帮助读者构建完整的知识体系。
三次握手(Three-way Handshake)是指在建立 TCP 连接时,客户端和服务器总共需要交换三个报文段。其主要目的是确认双方的接收能力和发送能力是否正常,并初始化序列号(ISN),为后续的数据可靠传输做准备。实质上,这是连接指定端口、同步双方序列号和确认号、交换窗口大小的过程。
初始状态下,客户端处于 Closed 状态,服务端处于 Listen 状态。
第一次握手: 客户端向服务端发送一个 SYN 报文,指明客户端的初始化序列号 ISN(x)。此时客户端进入 SYN_SEND 状态。
第二次握手: 服务端收到客户端的 SYN 报文后,会以自己的 SYN 报文作为应答,同时指定自己的初始化序列号 ISN(y)。并将客户端的 ISN + 1 作为 ACK 的值,表示已收到客户端的 SYN。此时服务端进入 SYN_RECV 状态。
第三次握手: 客户端收到服务端的 SYN 报文后,发送一个 ACK 报文,将服务器的 ISN + 1 作为 ACK 的值,表示已收到服务端的 SYN。此时客户端进入 ESTABLISHED 状态。服务端收到 ACK 后也进入 ESTABLISHED 状态,连接正式建立。
在 Socket 编程中,客户端执行 connect() 操作时会触发三次握手。
两次握手无法解决'已失效的连接请求'问题。如果只有两次握手:
三次握手确保了服务端能确认客户端的接收能力正常,避免了上述死锁和资源浪费情况。
半连接队列(Syn Queue): 服务器收到客户端 SYN 后,处于 SYN_RECV 状态,此时连接尚未完全建立。服务器将此类请求放入半连接队列。
全连接队列(Accept Queue):
完成三次握手后,连接进入 ESTABLISHED 状态,被放入全连接队列等待应用层调用 accept() 获取。
若队列满,可能导致丢包或拒绝新连接。系统参数如 net.ipv4.tcp_max_syn_backlog 可控制半连接队列长度。此外,SYN-ACK 重传次数有限制,默认通常为 5 次,超时后从半连接队列删除。
ISN(Initial Sequence Number)不是固定的。它随时间动态变化,通常每 4ms 加 1。这样设计的目的是防止在网络中延迟的旧分组在连接结束后再次到达,导致接收方错误解释数据。如果 ISN 固定,攻击者容易猜出后续确认号,进行欺骗攻击。
原理: 服务器在二次握手时分配资源,客户端在三次握手后分配资源。攻击者伪造大量不存在 IP 地址发送 SYN 包,服务器回复 SYN-ACK 并等待确认。由于源地址不存在,服务器不断重传直至超时,占用半连接队列,导致正常请求被丢弃,形成 DoS/DDoS 攻击。
检测:
使用 netstat -n -p TCP | grep SYN_RECV 查看大量半连接状态。
防御:
net.ipv4.tcp_syncookies = 1)。终止连接需经过四次挥手,由 TCP 的半关闭(Half-Close)特性决定。即一端结束发送后仍能接收另一端数据的能力。
假设客户端主动发起关闭:
第一次挥手: 客户端发送 FIN 报文,指定序列号 u。进入 FIN_WAIT1 状态,停止发送数据。
第二次挥手: 服务端收到 FIN,发送 ACK 报文,确认号 ack=u+1。进入 CLOSE_WAIT 状态。此时 TCP 处于半关闭状态。
第三次挥手: 服务端处理完剩余数据后,发送 FIN 报文,指定序列号 w。进入 LAST_ACK 状态。
第四次挥手: 客户端收到 FIN,发送 ACK 报文,确认号 ack=w+1。进入 TIME_WAIT 状态。等待 2MSL 后进入 CLOSED 状态。
服务端收到 ACK 后直接进入 CLOSED 状态。
关闭连接时,当服务端收到 FIN,可能还有数据要发送,不能立即关闭。因此先回复 ACK 告知收到 FIN,等所有数据发完后才发送 FIN。这导致了 ACK 和 FIN 分开发送,形成四次交互。
TIME_WAIT 状态也称为 2MSL 等待状态。MSL(Maximum Segment Lifetime)是报文段在网络中的最大生存时间。
停留 2MSL 的意义:
TIME_WAIT 的危害:
在高并发场景下,大量 TIME_WAIT 连接会耗尽端口资源。可通过设置 SO_REUSEADDR 选项允许重用本地端口,或调整内核参数减少 TIME_WAIT 数量。
理解 TCP 握手需了解报文结构。标准首部至少 20 字节,包含以下关键字段:
在生产环境中,针对 TCP 性能可进行如下调优:
sysctl -w net.ipv4.tcp_max_syn_backlog=2048
sysctl -w net.ipv4.tcp_syncookies=1
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
TCP 状态变迁图是理解连接管理的核心工具。粗实线箭头代表客户端状态变迁,虚线代表服务端。掌握三次握手与四次挥手的细节,不仅有助于应对面试,更能指导生产环境的网络故障排查与性能优化。在实际开发中,应关注队列溢出、端口耗尽及连接重置等异常情况,结合内核参数合理配置,确保服务稳定性。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online