面试题:怎么理解3 次握手与 4 次挥手:TCP 连接的建立与终止
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接、可靠的传输层协议,其核心特性之一就是通过三次握手建立连接和四次挥手终止连接来保证数据传输的可靠性。
一、TCP 三次握手(建立连接)
三次握手(Three-Way Handshake)是 TCP 协议中客户端和服务器建立连接的过程,目的是确保双方都能正常发送和接收数据,避免因网络延迟导致的无效连接。
握手过程详解
第一次握手(客户端 → 服务器)
- 客户端主动发起连接请求,发送一个SYN(Synchronize Sequence Number,同步序列编号) 报文段。
- 报文中包含:
SYN=1
(标志位,表示这是连接请求)、客户端初始序列号(seq=x
,随机生成的 32 位整数)。 - 此时客户端状态从
CLOSED
变为SYN-SENT
。
第二次握手(服务器 → 客户端)
- 服务器接收到 SYN 请求后,若同意连接,会回复一个SYN+ACK报文段。
- 报文中包含:
SYN=1
(服务器的同步请求)、ACK=1
(确认客户端的请求)、服务器初始序列号(seq=y
,随机生成)、确认号(ack=x+1
,表示已收到客户端的seq=x
)。 - 此时服务器状态从
LISTEN
变为SYN-RCVD
。
第三次握手(客户端 → 服务器)
- 客户端接收到 SYN+ACK 后,发送一个ACK报文段作为确认。
- 报文中包含:
ACK=1
(标志位)、序列号(seq=x+1
,基于客户端初始序列号递增)、确认号(ack=y+1
,表示已收到服务器的seq=y
)。 - 客户端状态从
SYN-SENT
变为ESTABLISHED
(连接建立)。 - 服务器接收到 ACK 后,状态从
SYN-RCVD
变为ESTABLISHED
,双方开始传输数据。
为什么需要三次握手?
- 避免重复连接:若客户端的 SYN 报文因网络延迟滞留,客户端超时后会重新发送 SYN。若采用两次握手,服务器可能对滞留的旧 SYN 建立无效连接,浪费资源;三次握手通过客户端的最终确认,确保双方对 “当前连接” 达成共识。
- 同步序列号:TCP 通过序列号保证数据有序性和不重复,三次握手过程中双方交换并确认初始序列号,为后续数据传输奠定基础。
二、TCP 四次挥手(终止连接)
四次挥手(Four-Way Wavehand)是 TCP 连接终止的过程,由于 TCP 是全双工通信(双方可同时发送数据),因此需要双方分别确认关闭各自的发送通道。
挥手过程详解
假设客户端主动发起断开连接请求:
第一次挥手(客户端 → 服务器)
- 客户端完成数据发送后,发送FIN(Finish,结束) 报文段,请求关闭连接。
- 报文中包含:
FIN=1
(标志位)、序列号(seq=u
,基于客户端已发送数据的序列号递增)。 - 客户端状态从
ESTABLISHED
变为FIN-WAIT-1
。
第二次挥手(服务器 → 客户端)
- 服务器接收到 FIN 后,回复ACK报文段确认收到请求,但可能仍有数据未发送完毕。
- 报文中包含:
ACK=1
、确认号(ack=u+1
)、序列号(seq=v
,基于服务器已发送数据的序列号递增)。 - 服务器状态从
ESTABLISHED
变为CLOSE-WAIT
,客户端接收到 ACK 后状态从FIN-WAIT-1
变为FIN-WAIT-2
,等待服务器发送剩余数据。
第三次挥手(服务器 → 客户端)
- 服务器完成所有数据发送后,发送FIN+ACK报文段,请求关闭自身的发送通道。
- 报文中包含:
FIN=1
、ACK=1
、序列号(seq=w
,服务器剩余数据发送完毕后的序列号)、确认号(ack=u+1
,重复确认客户端的 FIN)。 - 服务器状态从
CLOSE-WAIT
变为LAST-ACK
。
第四次挥手(客户端 → 服务器)
- 客户端接收到 FIN+ACK 后,发送ACK报文段确认服务器的关闭请求。
- 报文中包含:
ACK=1
、序列号(seq=u+1
)、确认号(ack=w+1
)。 - 客户端状态从
FIN-WAIT-2
变为TIME-WAIT
(等待一段时间,确保服务器收到 ACK),服务器接收到 ACK 后状态从LAST-ACK
变为CLOSED
。 - 客户端在
TIME-WAIT
等待2MSL(Maximum Segment Lifetime,报文最大生存时间,通常为 2 分钟) 后,状态变为CLOSED
,连接彻底终止。
为什么需要四次挥手?
- 全双工通信的独立性:TCP 双方可独立关闭发送通道。客户端先发送 FIN 表示 “我不再发送数据”,服务器先回复 ACK 确认 “收到关闭请求”,待自身数据发送完毕后再发送 FIN 表示 “我也不再发送数据”,最后客户端确认,因此需要四次交互。
- TIME-WAIT 的作用:防止最后一次 ACK 报文丢失导致服务器重发 FIN;确保网络中滞留的旧报文段已过期,避免干扰新连接。
三、三次握手与四次挥手对比
阶段 | 核心目的 | 关键标志位 | 状态变化核心节点 |
---|---|---|---|
三次握手 | 建立连接,同步序列号 | SYN、ACK | 客户端SYN-SENT →ESTABLISHED |
四次挥手 | 终止连接,释放资源 | FIN、ACK | 客户端FIN-WAIT-1 →TIME-WAIT |
总结
- 三次握手是 “请求 - 确认 - 再确认” 的过程,确保双方通信能力正常,为数据传输铺路。
- 四次挥手是 “关闭请求 - 确认 - 反向关闭请求 - 最终确认” 的过程,因全双工特性需分步释放发送通道。
- 两者共同体现了 TCP 协议的可靠性设计,通过状态管理和报文确认机制,保证连接的有序建立与终止。
四次挥手比三次握手多一次的核心原因更复杂,涉及 TCP 的双向关闭特性和半关闭状态的设计,而非单纯清理未处理数据。以下是具体分析:
一、三次握手与四次挥手的本质区别
TCP 是全双工协议,允许通信双方同时发送数据。因此,连接的建立和关闭存在本质差异:
- 三次握手(建立连接):是单向同步的过程。客户端发起连接请求,服务器确认并同步自身状态,客户端最终确认。双方的目标是达成 “双方都准备好发送数据” 的共识,无需分别处理两个方向的建立逻辑,因此三次交互即可完成。
- 四次挥手(关闭连接):是双向独立关闭的过程。通信双方(假设 A 先发起关闭)需要分别处理两个方向的连接关闭:A 先关闭 “发送数据” 的方向,B 确认后关闭自己 “接收数据” 的方向;随后 B 再关闭自己 “发送数据” 的方向,A 确认后关闭自己 “接收数据” 的方向。两个方向的关闭是独立的,因此需要四次交互。
二、四次挥手多一次的核心原因:双向关闭的独立性
假设客户端(A)先发起关闭,过程如下:
- 第一次挥手(A→B):A 发送
FIN
报文,告知 B:“我已完成数据发送,关闭我到你的发送方向”。此时 A 进入FIN_WAIT_1状态,不再向 B 发送数据,但仍可接收 B 的数据(半关闭状态)。 - 第二次挥手(B→A):B 收到
FIN
后,立即回复ACK
确认:“我知道你要关闭发送方向了”。此时 B 进入CLOSE_WAIT状态,A 收到后进入FIN_WAIT_2状态。
✅ 这一步的作用:确认 A 的关闭请求,但 B 可能还有未发送完的数据,因此不会立即关闭自己的发送方向。 - 第三次挥手(B→A):B 处理完剩余数据后,发送
FIN
报文,告知 A:“我也完成数据发送,关闭我到你的发送方向”。此时 B 进入LAST_ACK状态。
✅ 这一步是 B 独立发起的关闭请求,与 A 的关闭请求无关,是第二个方向的关闭启动。 - 第四次挥手(A→B):A 收到
FIN
后,回复ACK
确认:“我知道你要关闭发送方向了”。A 进入TIME_WAIT状态(等待超时确保 B 收到确认),最终关闭;B 收到ACK
后直接关闭。
关键:第二次挥手(B 的 ACK
)和第三次挥手(B 的 FIN
)无法合并,因为 B 可能在收到 A 的 FIN
后还有数据要发送,必须先确认 A 的关闭请求,再等待自己的数据发送完毕后,才能发起自己的 FIN
。这两个动作在时间上是分离的,因此必须分成两次报文,导致比三次握手多一次交互。
三、关于 “清理未处理数据” 的补充
四次挥手的设计确实为 “清理数据” 提供了空间,但这是结果而非原因:
- B 在收到 A 的
FIN
后(第一次挥手),进入CLOSE_WAIT状态,此时可以继续向 A 发送未处理完的数据(因为 A 仍能接收),直到数据发送完毕后再发FIN
(第三次挥手)。 - 若 B 没有未处理数据,理论上可以将第二次挥手(
ACK
)和第三次挥手(FIN
)合并,但 TCP 协议允许这种情况(此时四次挥手会变成三次),但实际中因数据处理的不确定性,通常需要四次。
总结
四次挥手比三次握手多一次的核心原因是:
TCP 需要分别处理两个方向的连接关闭,而这两个方向的关闭请求(FIN
)由通信双方各自独立发起,且中间可能存在数据传输的延迟,因此必须通过四次交互完成双向关闭的确认。 清理未处理数据是这一过程的常见场景,但并非根本原因。
应用场景举例说明四次挥手比三次握手多一次的必要性
详细解释半关闭状态的作用
网络断开时数据丢失怎么办?