跳到主要内容

TCP 三次握手与四次挥手

在学习 HTTP 协议时,我们经常会看到"三次握手"和"四次挥手"这两个词。它们其实是 TCP 协议的概念。TCP(Transmission Control Protocol,传输控制协议)是一种可靠的传输协议,HTTP 就是建立在 TCP 之上的。

可以把 TCP 想象成打电话:在正式通话之前,双方需要先确认彼此都能听到对方说话;通话结束时,也要礼貌地互相道别,而不是直接挂断。

三次握手:建立连接

三次握手就像打电话时的开场确认:

sequenceDiagram
participant 客户端
participant 服务器

客户端->>服务器: ① SYN:你好,能听到吗?
服务器->>客户端: ② SYN + ACK:能听到,你能听到我吗?
客户端->>服务器: ③ ACK:能听到,我们开始吧!

Note over 客户端,服务器: 连接建立成功,可以传输数据了

每一步的作用

步骤发送方内容目的
第一次客户端 → 服务器SYN(同步请求)客户端告诉服务器:我想建立连接
第二次服务器 → 客户端SYN + ACK(同步 + 确认)服务器回应:收到了,我也准备好了
第三次客户端 → 服务器ACK(确认)客户端确认:好的,我们开始通信吧

为什么是三次?

三次握手的核心目的是确认双方的发送和接收能力都正常

  • 第一次握手后:服务器知道客户端能发送
  • 第二次握手后:客户端知道服务器能发送和接收
  • 第三次握手后:服务器知道客户端能接收

如果只有两次握手,服务器无法确认客户端是否能正常接收数据,可能会导致资源浪费。

四次挥手:断开连接

四次挥手就像礼貌地结束通话:

sequenceDiagram
participant 客户端
participant 服务器

客户端->>服务器: ① FIN:我说完了,准备挂了
服务器->>客户端: ② ACK:好的,我知道了
Note over 服务器: 服务器可能还有数据要发送...
服务器->>客户端: ③ FIN:我也说完了,可以挂了
客户端->>服务器: ④ ACK:好的,再见!

Note over 客户端,服务器: 连接断开

每一步的作用

步骤发送方内容目的
第一次客户端 → 服务器FIN(结束请求)客户端:我的数据发完了
第二次服务器 → 客户端ACK(确认)服务器:收到,但我可能还有数据要发
第三次服务器 → 客户端FIN(结束请求)服务器:我也发完了,可以断开了
第四次客户端 → 服务器ACK(确认)客户端:好的,再见

为什么是四次?

断开连接需要四次,是因为 TCP 连接是双向的,每个方向都需要单独关闭:

  • 客户端说"我说完了"(第一次),服务器确认(第二次)—— 关闭客户端到服务器的方向
  • 服务器说"我也说完了"(第三次),客户端确认(第四次)—— 关闭服务器到客户端的方向

这就像打电话时,你说完了不代表对方也说完了,需要双方都确认没有话要说,才能挂断电话。

总结

对比项三次握手四次挥手
目的建立连接断开连接
次数3 次4 次
关键标志SYN、ACKFIN、ACK
发起方客户端任意一方(通常是客户端)

理解了 TCP 的三次握手和四次挥手,再回头看 HTTP 版本演进 中提到的"短连接"和"持久连接",就更容易理解为什么 HTTP/1.0 的短连接效率低下——每次请求都要经历一次完整的握手和挥手过程。

面试常见问题

Q1:为什么握手是三次,而挥手是四次?

握手三次:建立连接时,服务器收到 SYN 后可以把 SYN 和 ACK 合并在一条消息中发送,所以只需要三次。

挥手四次:断开连接时,服务器收到客户端的 FIN 后,可能还有数据没发完,所以只能先回复 ACK 表示"我知道了",等数据发完后再发送 FIN。这两步无法合并,所以需要四次。

Q2:如果第三次握手丢失会怎样?

  • 客户端认为连接已建立,开始发送数据
  • 服务器没收到 ACK,会重传第二次握手的 SYN+ACK
  • 如果多次重传后仍未收到 ACK,服务器会放弃连接

Q3:什么是 SYN 洪泛攻击?

攻击者伪造大量不同 IP 地址发送 SYN 请求,服务器回复 SYN+ACK 后等待第三次握手,但永远等不到。这会导致服务器维护大量"半连接",耗尽资源。

防御方式:SYN Cookie、限制半连接数量、缩短超时时间等。

Q4:什么是 TIME_WAIT 状态?为什么需要它?

客户端发送最后一个 ACK 后,不会立即关闭连接,而是进入 TIME_WAIT 状态,等待 2 倍的 MSL(Maximum Segment Lifetime,报文最大生存时间)。

原因有两个

  1. 确保最后的 ACK 能到达:如果服务器没收到 ACK,会重发 FIN,客户端需要能够响应
  2. 让旧连接的数据包消失:防止旧连接的延迟数据包影响新连接

Q5:四次挥手能变成三次吗?

可以。如果服务器收到 FIN 时刚好没有数据要发送,可以把 ACK 和 FIN 合并成一条消息,这样就变成了三次挥手。这种情况叫做延迟确认(Delayed ACK)。

Q6:握手过程中的序列号有什么用?

序列号(Sequence Number)用于:

  • 保证数据按序到达:接收方根据序列号重新排列乱序的数据包
  • 防止旧连接干扰:每次连接使用不同的初始序列号(ISN),避免旧数据包被误认为是新连接的数据