为什么TCP是三次握手?
TCP 三次握手的本质,是在不可靠的 IP 信道上,以最小的通信开销,完成两个核心目标:
- 确认通信双方全双工的发送、接收能力均正常;
- 同步双方的初始序列号 ISN,为后续的可靠传输、按序交付、重传机制奠基,同时规避历史失效连接导致的服务端资源浪费。
两次握手无法解决核心缺陷,四次握手则冗余无必要。
标准三次握手极简流程
TCP 是面向连接的可靠全双工传输协议,连接建立的三次握手由 RFC 793 标准定义:
- 第一次握手(客户端→服务端 SYN) :客户端发送同步报文,携带自身初始序列号
ISN(c),进入SYN_SENT状态,发起连接请求。 - 第二次握手(服务端→客户端 SYN+ACK) :服务端收到 SYN 后,回复同步 + 确认报文,携带自身初始序列号
ISN(s),同时确认号为ISN(c)+1,进入SYN_RCVD状态。 - 第三次握手(客户端→服务端 ACK) :客户端收到 SYN+ACK 后,回复确认报文,确认号为
ISN(s)+1,进入ESTABLISHED状态;服务端收到该 ACK 后,也进入ESTABLISHED状态,全双工连接正式建立。
为什么必须是三次,两次握手有致命缺陷
两次握手无法完成双向收发能力的全量确认
全双工可靠传输的前提,是双方都能确认对方的收发能力正常:
- 第一次握手后,服务端仅能确认:客户端的发送能力、服务端的接收能力正常;
- 第二次握手后,客户端能确认双方收发能力均正常,但服务端完全无法验证自己的发送能力是否正常,也无法确认客户端的接收能力是否正常。
若仅两次握手就建立连接,服务端会单方面认为连接就绪并开始发送数据。如果客户端根本没收到服务端的 SYN+ACK 报文,会完全无视后续数据,不仅传输无效,还会持续占用服务端资源。
两次握手无法完成双向 ISN 同步,失去可靠传输的核心基础
TCP 的按序交付、重复报文去重、丢包重传、流量控制,完全依赖字节级的序列号实现。初始序列号 ISN 是动态随机生成的(防止被预测、规避历史报文干扰),必须让双方都确认对方已收到自己的 ISN。
两次握手场景下,客户端能确认服务端收到了自己的 ISN,但服务端无法确认客户端是否收到了自己的 ISN。后续服务端基于ISN(s)发送的数据包,客户端若未收到 ISN,将无法正确校验和确认,直接导致传输不可靠。
两次握手无法抵御历史失效连接,极易造成服务端资源耗尽
这是 TCP 设计最核心的考量之一。网络环境不可靠,客户端发送的 SYN 可能因网络拥堵长时间滞留,客户端超时重发 SYN 并完成传输、断开连接后,滞留的旧 SYN 才到达服务端。
- 两次握手:服务端收到历史失效 SYN 后,会直接建立连接、分配完整的传输控制块(TCB)资源,而客户端无连接意图,不会发送任何数据,服务端资源会被大量无效连接占用,极易被 SYN 洪水攻击打垮。
- 三次握手:服务端收到 SYN 后,仅将连接放入半连接队列,不分配完整资源;只有收到客户端的第三次 ACK,才会正式建立连接。对于历史失效 SYN,客户端不会回复 ACK,服务端会超时释放半连接资源,从根源上规避无效资源占用。
为什么四次握手完全没必要
全双工通信的双向同步 + 双向确认,无需拆分为四次。
服务端的SYN(同步自身 ISN)和 ACK(确认客户端的 SYN) 可以合并在同一个报文段中发送,无需拆分两次。
若强行拆分为四次(客户端 SYN→服务端 ACK→服务端 SYN→客户端 ACK),会额外增加一次网络交互,无端增加连接建立延迟、浪费带宽,完全没有必要。
三次握手已经能完成所有核心目标,是兼顾可靠性和效率的最优解。