Reading Mode

破解TCP三次握手四次挥手的本质:不只是面试题的技术深度解析

本文将从本质出发,用通俗易懂的语言,为大家揭开TCP连接建立和断开过程的神秘面纱。

发布日期

2025/04/21

更新时间

尚未更新

难度

入门

预估阅读

约 10 分钟

作者

SecLab安全实验室

面试中经常被问到”三次握手,四次挥手”的问题。很多时候,我们都能条件反射式地背出标准答案:第一次怎样,第二次怎样…但背后的原理和逻辑,却很少有人能真正说清楚。

本文将从本质出发,用通俗易懂的语言,为大家揭开TCP连接建立和断开过程的神秘面纱。

一、什么是TCP连接?

在谈论”三次握手,四次挥手”前,我们需要理解什么是TCP连接。 想象一下,TCP连接就像是两个人之间的电话通话。在通话前,你需要拨号、等待对方接听、互相确认身份,这个过程就是”三次握手”;通话结束时,双方互相道别、挂断电话的过程,就是”四次挥手”。

从技术角度看,TCP是一种面向连接的单播协议,所谓的”连接”,其实只是通信双方内存中存储的一些信息,比如对方的IP地址、端口号等。这些信息让TCP能够提供可靠的、有序的数据传输服务。

二、为什么需要”三次握手”?

很多人困惑:为什么建立连接需要三次握手,而不是两次或四次?

通俗理解三次握手

想象你(客户端)和朋友(服务器)隔着一条嘈杂的马路喊话:

  1. 第一次握手:你大喊:“嘿!能听到我说话吗?“(客户端发送SYN)
  2. 第二次握手:朋友回应:“听到了!你能听到我说话吗?“(服务器返回SYN+ACK)
  3. 第三次握手:你回答:“我也听到你的了!“(客户端发送ACK)

至此,你们确认了一个重要事实:双方都能发送信息,也都能接收信息。这正是通信的基础条件。

技术解释

从技术角度,三次握手的目的是:

  1. 确认双方的接收、发送能力正常
  • 第一次握手:客户端证明自己的发送能力正常,服务端证明自己的接收能力正常
  • 第二次握手:服务端证明自己的发送能力正常,客户端证明自己的接收能力正常
  • 第三次握手:客户端再次证明自己的发送能力正常,服务端再次证明自己的接收能力正常
  1. 交换初始序列号(ISN)
  • 序列号用于追踪TCP数据流中的字节,确保数据有序传输
  • 随机选择序列号可以增强安全性,防止攻击者猜测序列号

如果只有两次握手,服务端无法确认客户端的接收能力;如果有四次握手,则会造成额外的网络开销。因此,三次握手是最优选择。

三、四次挥手:为什么关闭连接需要四步?

关闭连接为什么需要四次挥手,而不是像建立连接那样三次就够了呢?

通俗理解四次挥手

继续用电话通话来比喻:

  1. 第一次挥手:你说”我这边说完了,没什么要说的了”(客户端发FIN)
  2. 第二次挥手:朋友回答”好的,我知道你没话说了,但我可能还有话要说”(服务端回ACK)
  3. 第三次挥手:朋友又说”我也说完了,可以挂电话了”(服务端发FIN)
  4. 第四次挥手:你回答”好的,拜拜”(客户端回ACK)

关键在于:当你表示要结束通话时,对方可能还有话要说。这就是为什么需要四次挥手—因为TCP是双向通信的,每个方向都需要单独关闭。

技术解释

从技术角度:

  1. TCP连接是全双工的,数据可以在两个方向上独立传输
  2. 当一方发送FIN时,仅表示它不再发送数据,但仍可接收数据
  3. 接收到FIN的一方必须先回复ACK,然后等待上层应用程序决定何时关闭自己的发送方向
  4. 因此,关闭连接需要双方各自发送一个FIN和一个ACK,总共四个报文段

这就解释了为什么建立连接是三次握手,而关闭连接是四次挥手。

四、深入理解TCP头部和状态转换

理解三次握手和四次挥手的核心,是了解TCP头部中的关键字段和连接状态转换。

TCP头部的关键字段

TCP头部包含许多重要信息,但在握手和挥手过程中,最关键的是:

  1. 序列号(Sequence Number):标识发送的数据字节流的位置
  2. 确认号(Acknowledgment Number):期望收到的下一个字节的序列号
  3. 标志位:
  • SYN:请求建立连接
  • ACK:确认收到的数据
  • FIN:请求关闭连接
  • RST:重置连接

连接状态转换

TCP连接从创建到关闭,会经历以下状态:

1. 连接建立(三次握手)

  • 客户端开始(CLOSED) 客户端一开始是“关闭”状态,什么都没做。
  • 服务端开始(LISTEN) 服务端在“监听”状态,等着有人来联系。

第一步

  • 客户端发送SYN 客户端想要和服务端说话,发出“我想和你建立连接!”(SYN)。

第二步

  • 服务端收到SYN,回复SYN+ACK 服务端收到了请求,回复“我收到了你的请求,也准备好了!”(SYN+ACK)。

第三步

  • 客户端收到SYN+ACK,回复ACK

    客户端收到了服务端的回复,再发一个“我也准备好了!”(ACK)。

  • 现在,两边都进入“ESTABLISHED”(已建立)状态,可以正常通信了。


2. 连接关闭(四次挥手)

主动关闭方(通常是客户端)

  1. 客户端在通信中(ESTABLISHED) 聊天正在进行。
  2. 客户端想挂电话,发送FIN(FIN_WAIT_1) 客户端说:“我这边没什么要说的了,我要挂电话了!”(发送FIN)
  3. 收到服务端的ACK(FIN_WAIT_2) 服务端回复:“我知道你要挂了!”(ACK)
  4. 收到服务端的FIN,回复ACK,进入TIME_WAIT 服务端说:“我也说完了,现在可以挂电话了!”(发送FIN),客户端最后说“好的,再见!”(ACK), 然后等一会儿,确保对方收到了,才彻底挂断(TIME_WAIT)。
  5. 等待超时后,进入CLOSED状态 客户端正式挂断,回到关闭状态。

被动关闭方(通常是服务端)

  1. 服务端在通信中(ESTABLISHED) 正常通信。
  2. 收到客户端的FIN,回复ACK(CLOSE_WAIT) 客户端说要挂了,服务端回复“我知道了!”(ACK)
  3. 服务端也说完了,发送FIN(LAST_ACK) 服务端说:“我也说完了,也要挂了!”(发送FIN)
  4. 收到客户端的ACK后,进入CLOSED状态 客户端说“好的,再见!”(ACK),服务端彻底挂断。

五、常见问题

SYN Flood攻击

SYN Flood是一种常见的DoS攻击,攻击者发送大量SYN包却不完成握手,导致服务器资源耗尽。

防御措施包括:

  1. SYN Cookie:不在收到SYN时立即分配资源
  2. 减少SYN+ACK重试次数:调整tcp_synack_retries参数
  3. 增大半连接队列:调整tcp_max_syn_backlog参数

连接队列溢出

服务器维护两种队列:

  1. 半连接队列:存放SYN_RECEIVED状态的连接
  2. 全连接队列:存放ESTABLISHED但未被应用accept的连接

当这些队列满时,新连接可能被丢弃或重置,可通过以下命令检查:

netstat -s | egrep "listen|LISTEN"  
ss -lnt

六、总结

TCP的”三次握手,四次挥手”看似复杂,实际是保证可靠通信的必要设计。三次握手确保双方都具备收发能力并交换序列号;四次挥手则保证双向数据流都能完整关闭。

理解这些机制的本质,比单纯记住步骤更重要。作为程序员,我们应该培养”刨根问底”的精神,不仅知其然,更要知其所以然。

下次面试官再问你”三次握手,四次挥手”,希望你能自信地从本质出发,展示你深刻的理解,而不只是机械地背诵步骤。

TCP三次握手TCP四次挥手三次握手原理网络协议分析