TCP(传输控制协议)是面向连接、可靠的全双工传输层协议,其 “三次握手” 用于建立可靠连接,“四次挥手” 用于优雅关闭连接,二者共同保障数据传输的安全性和完整性。以下从核心目的、详细流程、关键细节、常见问题四个维度,全面解析这两个策略:
一、TCP 三次握手:建立可靠连接
1. 核心目的
确保客户端与服务器双方的 **“发送能力” 和 “接收能力” 均正常 **,并协商初始序列号(用于后续数据传输的有序性和去重),最终建立双向通信的 TCP 连接。
2. 详细流程(含报文与状态变化)
TCP 连接建立过程中,客户端与服务器通过交换SYN(同步报文,用于发起连接)和ACK(确认报文,用于确认接收)两类报文完成握手,双方状态从CLOSED逐步过渡到ESTABLISHED(连接已建立)。
| 步骤 | 发送方 | 接收方 | 发送报文 | 核心作用 | 双方状态变化 |
|---|---|---|---|---|---|
| 1 | 客户端 | 服务器 | SYN(Seq=X,随机初始值) | 客户端向服务器发起连接请求,告知服务器 “我要连接你,我的初始序列号是 X” | 客户端:CLOSED→SYN_SENT |
| 2 | 服务器 | 客户端 | SYN+ACK(Seq=Y,Ack=X+1) | 服务器确认收到客户端请求(Ack=X+1 表示 “已收到 X 及之前的所有数据”),同时发起自己的连接请求(Seq=Y) | 服务器:CLOSED→SYN_RCVD |
| 3 | 客户端 | 服务器 | ACK(Seq=X+1,Ack=Y+1) | 客户端确认收到服务器的连接请求(Ack=Y+1),告知服务器 “你的请求我已收到,连接可正常使用” | 客户端:SYN_SENT→ESTABLISHED;服务器:SYN_RCVD→ESTABLISHED |
3. 关键细节
-
初始序列号(Seq)的随机性:Seq 不能固定为 0(或固定值),否则易被攻击者伪造报文(如重复利用旧连接的序列号),随机 Seq 可提升安全性。
-
“三次” 的必要性:
若仅两次握手(客户端发 SYN→服务器回 SYN+ACK,直接建立连接),服务器无法确认 “客户端是否能接收自己的报文”—— 若客户端的ACK丢失,服务器会误以为连接已建立,持续发送数据,导致资源浪费。三次握手通过客户端的最后一次ACK,确保双方收发能力均正常。
- 连接建立后的准备:握手完成后,双方会初始化 “发送缓冲区”“接收缓冲区” 和 “滑动窗口”(用于流量控制),为后续数据传输铺路。
二、TCP 四次挥手:优雅关闭连接
1. 核心目的
TCP 是全双工协议(客户端与服务器可同时发送数据),四次挥手的核心是 “双方分别关闭自己的发送通道”,确保所有数据传输完成后再释放连接,避免数据丢失。
2. 详细流程(含报文与状态变化)
关闭过程中,双方通过FIN(结束报文,用于告知 “我不再发送数据”)和ACK报文交互,状态从ESTABLISHED逐步过渡到CLOSED,关键是 “分两次关闭发送通道”。
| 步骤 | 发送方 | 接收方 | 发送报文 | 核心作用 | 双方状态变化 |
|---|---|---|---|---|---|
| 1 | 客户端 | 服务器 | FIN(Seq=X,Ack=Y) | 客户端告知服务器 “我已无数据要发送,关闭我的发送通道”(仍可接收服务器数据) | 客户端:ESTABLISHED→FIN_WAIT_1 |
| 2 | 服务器 | 客户端 | ACK(Seq=Y,Ack=X+1) | 服务器确认收到客户端的关闭请求,告知 “你的发送通道已关闭,我会继续发剩余数据” | 服务器:ESTABLISHED→CLOSE_WAIT;客户端:FIN_WAIT_1→FIN_WAIT_2 |
| 3 | 服务器 | 客户端 | FIN(Seq=Y+M,Ack=X+1) | 服务器发送完所有数据后,告知客户端 “我也无数据要发送,关闭我的发送通道” | 服务器:CLOSE_WAIT→LAST_ACK |
| 4 | 客户端 | 服务器 | ACK(Seq=X+1,Ack=Y+M+1) | 客户端确认收到服务器的关闭请求,告知 “你的发送通道已关闭,等待一段时间后我会释放连接” | 客户端:FIN_WAIT_2→TIME_WAIT;服务器:LAST_ACK→CLOSED |
3. 关键细节
- “四次” 的必要性:
全双工特性导致双方需单独关闭发送通道 —— 步骤 1-2 关闭 “客户端→服务器” 的发送通道,步骤 3-4 关闭 “服务器→客户端” 的发送通道;若仅三次挥手,无法确保某一方的剩余数据完全传输。
- TIME_WAIT 状态(客户端特有) :
客户端发送最后一个ACK后,不会立即关闭连接,而是进入TIME_WAIT状态(默认等待2MSL,MSL 是 “报文最大生存时间”,通常为 1-2 分钟),目的是:
-
确保服务器能收到最后一个ACK(若服务器没收到,会重发FIN,客户端在 TIME_WAIT 内可再次回复);
-
避免新连接复用旧端口时,收到旧连接的残留报文(2MSL 可确保网络中所有旧报文失效)。
- CLOSE_WAIT 状态(服务器特有) :
若服务器长时间处于CLOSE_WAIT,通常是 “服务器未正确调用close()接口关闭连接”(如代码漏洞导致资源泄漏),需排查业务逻辑。
三、三次握手与四次挥手的核心区别
| 对比维度 | 三次握手(建立连接) | 四次挥手(关闭连接) |
|---|---|---|
| 核心目标 | 确认双方收发能力,协商初始序列号 | 分阶段关闭双工通道,确保数据传输完成 |
| 报文类型 | SYN、SYN+ACK、ACK | FIN、ACK、FIN、ACK |
| 状态变化 | 客户端:CLOSED→SYN_SENT→ESTABLISHED;服务器:CLOSED→SYN_RCVD→ESTABLISHED | 客户端:ESTABLISHED→FIN_WAIT_1→FIN_WAIT_2→TIME_WAIT→CLOSED;服务器:ESTABLISHED→CLOSE_WAIT→LAST_ACK→CLOSED |
| 关键特殊状态 | 无特殊等待状态 | 客户端有TIME_WAIT,服务器有CLOSE_WAIT |
| 耗时 | 短(通常 10-100ms,取决于网络延迟) | 长(含 TIME_WAIT,通常 1-2 分钟) |
四、面试高频问题解答
1. 为什么三次握手不能改成两次?
- 两次握手无法确保 “客户端能接收服务器的报文”:若客户端的ACK丢失,服务器会误以为连接已建立,持续发送数据,导致服务器资源浪费;三次握手通过客户端的最后一次ACK,确保双方收发能力均正常,是 “最低成本的可靠连接方案”。
2. 为什么四次挥手需要 TIME_WAIT 状态?
- 核心是 “容错” 和 “防干扰”:
-
容错:确保服务器收到最后一个ACK(避免服务器重发FIN时客户端已关闭,导致服务器永久处于LAST_ACK);
-
防干扰:2MSL 内网络中旧连接的报文会失效,避免新连接复用旧端口时收到旧报文,导致数据错乱。
3. TCP 连接建立后,若客户端突然崩溃,服务器如何处理?
- 服务器通过Keep-Alive(保活机制) 检测:默认每隔 2 小时发送一个探测报文,若连续 3 次(每次间隔 75 秒)未收到客户端响应,服务器会认为客户端已下线,主动关闭连接,释放资源。
总结
TCP 三次握手和四次挥手是 “可靠传输” 的基石:
-
三次握手通过 “双向确认” 建立连接,确保通信双方具备正常收发能力;
-
四次挥手通过 “分阶段关闭” 释放连接,确保全双工模式下数据不丢失;
二者的设计充分体现了 TCP 协议 “安全优先、优雅容错” 的核心思想,也是面试中考察 “网络底层原理” 的高频考点。