1. 引言
TCP(Transmission Control Protocol,传输控制协议)是互联网中最核心的传输层协议之一,它为应用层提供可靠、面向连接的字节流服务。在 TCP 建立连接和断开连接的过程中,三次握手与四次挥手是两个最基础也最重要的机制。理解这两个过程,是深入掌握网络编程、排查连接异常的前提。
2. TCP 报文段中的关键标志位
在讲解握手与挥手之前,先了解 TCP 报文段头部中几个关键标志位,它们是整个流程的核心。
- SYN(Synchronize):同步标志,用于建立连接时同步序列号。
- ACK(Acknowledgment):确认标志,表示确认号有效,用于确认收到对方的数据。
- FIN(Finish):结束标志,表示发送方数据已发送完毕,请求断开连接。
- SEQ(Sequence Number):序列号,表示本报文段第一个字节的序号。
- ACK Number(确认号):表示期望收到对方下一个字节的序号。
此外,TCP 连接是全双工的,即数据可以在两个方向上独立传输,因此连接建立和断开都需要在两个方向上分别确认。
3. 三次握手:建立连接
3.1 为什么需要三次握手
三次握手的核心目的有三个:
- 确认双方的收发能力:确保客户端和服务端都能正确发送和接收数据。
- 同步双方的初始序列号:为后续可靠传输奠定基础。
- 防止历史失效连接请求:避免因网络延迟导致旧连接请求误建立新连接。
3.2 三次握手的具体过程
假设客户端为 A,服务端为 B,整个过程如下:
- 第一次握手(客户端发送 SYN):客户端向服务端发送一个 SYN 报文段,其中 SYN=1,并携带一个初始序列号 seq=x。此时客户端进入 SYN_SENT(同步已发送)状态。
- 第二次握手(服务端回复 SYN+ACK):服务端收到 SYN 报文后,如果同意建立连接,则回复一个 SYN+ACK 报文段,其中 SYN=1、ACK=1,确认号 ack=x+1,并携带自己的初始序列号 seq=y。此时服务端进入 SYN_RCVD(同步已接收)状态。
- 第三次握手(客户端回复 ACK):客户端收到 SYN+ACK 报文后,再向服务端发送一个 ACK 报文段,其中 ACK=1,确认号 ack=y+1,序列号 seq=x+1。此时客户端进入 ESTABLISHED(已建立连接)状态;服务端收到该 ACK 后也进入 ESTABLISHED 状态,连接正式建立。
3.3 三次握手的图示

3.4 为什么不是两次或四次
如果只有两次握手,服务端无法确认客户端是否收到了自己的 SYN+ACK 报文,也无法防止历史失效连接请求导致的资源浪费。而三次握手已经能够可靠地同步双方序列号并确认收发能力,四次则没有必要,反而增加延迟。因此三次握手是可靠性与效率之间的最佳平衡。
4. 四次挥手:断开连接
4.1 为什么需要四次挥手
由于 TCP 连接是全双工的,每个方向都必须独立关闭。当一方完成数据发送后,可以发送 FIN 报文关闭该方向的传输,但此时仍可以接收对方的数据。因此断开连接需要四次交互,分别关闭两个方向的数据通道。
4.2 四次挥手的具体过程
假设客户端主动发起断开连接,整个过程如下:
- 第一次挥手(客户端发送 FIN):客户端发送 FIN 报文段,其中 FIN=1,序列号 seq=u,表示客户端数据已发送完毕,请求断开连接。客户端进入 FIN_WAIT_1(终止等待 1)状态。
- 第二次挥手(服务端回复 ACK):服务端收到 FIN 报文后,回复 ACK 报文段,其中 ACK=1,确认号 ack=u+1,序列号 seq=v。此时服务端进入 CLOSE_WAIT(关闭等待)状态,客户端收到 ACK 后进入 FIN_WAIT_2(终止等待 2)状态。此时服务端仍可能继续发送数据。
- 第三次挥手(服务端发送 FIN):当服务端的数据也发送完毕后,服务端发送 FIN 报文段,其中 FIN=1,ACK=1,序列号 seq=w,确认号 ack=u+1。服务端进入 LAST_ACK(最后确认)状态。
- 第四次挥手(客户端回复 ACK):客户端收到 FIN 报文后,回复 ACK 报文段,其中 ACK=1,确认号 ack=w+1,序列号 seq=u+1。客户端进入 TIME_WAIT(时间等待)状态,服务端收到 ACK 后进入 CLOSED(关闭)状态。客户端在等待 2MSL(最大报文段生存时间)后进入 CLOSED 状态,连接彻底关闭。
4.3 四次挥手的图示

4.4 为什么客户端要等待 2MSL
客户端在发送最后一个 ACK 后进入 TIME_WAIT 状态,并等待 2MSL 时间,原因主要有两点:
- 确保最后一个 ACK 能到达服务端:如果该 ACK 丢失,服务端会重发 FIN,客户端需要能够再次回复 ACK。若客户端立即关闭,则无法响应重发的 FIN。
- 让旧报文在网络中自然消失:等待 2MSL 可以确保本次连接的所有报文段都在网络中消失,避免影响后续使用相同端口的新连接。
5. 常见问题与面试要点
5.1 三次握手中可以携带数据吗
第一次和第二次握手不能携带数据,因为此时连接尚未建立,若携带数据可能造成资源浪费和安全隐患。第三次握手时连接已基本建立,可以携带数据。
5.2 为什么挥手需要四次而握手只需要三次
握手时,服务端的 SYN 和 ACK 可以在同一个报文段中发送,因为服务端在收到 SYN 后可以立即同步自己的序列号并确认客户端的序列号。而挥手时,服务端收到 FIN 后可能仍有数据需要发送,因此 ACK 和 FIN 不能合并,需要分两次发送,所以挥手需要四次。
5.3 大量 TIME_WAIT 状态如何处理
在高并发场景下,主动关闭连接的一方可能出现大量 TIME_WAIT 状态的连接,占用端口资源。常见的优化手段包括:开启 TCP 时间戳选项、调整 MSL 值、复用 TIME_WAIT 连接(如开启 tcp_tw_reuse)等,但需结合具体业务场景谨慎使用。
6. 总结
三次握手通过 SYN、SYN+ACK、ACK 三次交互,可靠地建立了全双工连接并同步了双方序列号;四次挥手则通过 FIN、ACK、FIN、ACK 四次交互,分别关闭两个方向的数据通道,确保数据完整传输后安全断开。理解这两个过程,不仅有助于掌握 TCP 协议的本质,也是排查网络故障、优化服务性能的重要基础。