TCP 三次握手 & 四次挥手
一、TCP 三次握手(建立连接)
核心目的
确保双方收发能力都正常,同步双方初始序列号(ISN),建立可靠的 TCP 连接(为后续数据传输做准备)。
核心标识说明
-
SYN:同步序列号,用于发起连接、同步初始序列号
-
ACK:确认应答,用于确认收到对方的数据
-
ISN:随机初始序列号(每端独立生成,避免历史数据干扰)
流程图(mermaid格式,Markdown可直接渲染)
暂时无法在豆包文档外展示此内容
详细步骤
-
第一次握手(客户端 → 服务端):客户端主动发起连接,发送 SYN=1,携带自己的初始序列号 seq=x;客户端状态变为 SYN_SENT(等待服务端响应)。
-
第二次握手(服务端 → 客户端):服务端收到 SYN 后,确认客户端能发,同时向客户端发起同步(SYN=1),携带自己的初始序列号 seq=y;并回复 ACK=1,确认号 ack=x+1(表示"我收到了你发送的 x 及之前的所有数据");服务端状态变为 SYN_RCVD。
-
第三次握手(客户端 → 服务端):客户端收到服务端的 SYN+ACK 后,确认服务端能收能发,回复 ACK=1,确认号 ack=y+1;客户端状态变为 ESTABLISHED,服务端收到 ACK 后也变为 ESTABLISHED,连接正式建立。
二、TCP 四次挥手(断开连接)
核心目的
TCP 是双向通信协议,双方需独立关闭各自的发送通道,确保双方所有数据都已传输完成,再彻底断开连接(避免数据丢失)。
核心标识说明
-
FIN:结束标志,用于发起关闭连接请求(表示"我没有数据要发送了")
-
ACK:确认应答,与三次握手一致,用于确认收到 FIN 或数据
流程图(mermaid格式,Markdown可直接渲染)
暂时无法在豆包文档外展示此内容
详细步骤
-
第一次挥手(客户端 → 服务端):客户端无更多数据要发送,发送 FIN=1,携带当前序列号 seq=u;客户端状态变为FIN_WAIT_1(等待服务端确认)。
-
第二次挥手(服务端 → 客户端):服务端收到 FIN 后,回复 ACK=1,确认号 ack=u+1;此时服务端仍可向客户端发送未传完的数据,客户端状态变为 FIN_WAIT_2(等待服务端发起关闭)。
-
第三次挥手(服务端 → 客户端):服务端发送完所有剩余数据后,发送 FIN=1,携带当前序列号 seq=v;服务端状态变为 LAST_ACK(等待客户端确认)。
-
第四次挥手(客户端 → 服务端):客户端收到 FIN 后,回复 ACK=1,确认号 ack=v+1;客户端状态变为 TIME_WAIT(等待 2MSL 后彻底关闭,防止服务端没收到 ACK 重发 FIN),服务端收到 ACK 后直接变为 CLOSED。
三、高频场景面试题(含解析,适配面试问答)
以下是面试中最常考的 8 道场景题,解析直击考点,避免冗余,直接记核心即可。
★ 三次握手相关面试题
- 为什么 TCP 建立连接需要三次握手,而不是两次?
核心解析:核心是「确认双方收发能力都正常」,避免"失效连接请求"导致服务端资源浪费。
假设两次握手:客户端发送的 SYN(连接请求)因网络延迟,很久后才到达服务端,服务端以为是新请求,回复 SYN+ACK 后就建立连接、占用资源,但客户端早已超时关闭,服务端会一直等待客户端数据,造成资源泄漏。
三次握手的第三次,客户端会确认服务端的 SYN+ACK,只有双方都确认"对方能收能发",才建立连接,从根源避免上述问题。
- 三次握手过程中,客户端/服务端的状态变化是什么?
核心解析(记简写即可):
-
客户端:CLOSED → SYN_SENT → ESTABLISHED
-
服务端:CLOSED → LISTEN → SYN_RCVD → ESTABLISHED
- 三次握手时,SYN 为什么不能携带数据?
核心解析:此时连接尚未建立,服务端还未确认客户端的收发能力,若 SYN 携带数据,可能导致数据丢失(服务端未准备好接收);且 SYN 是"连接请求",核心目的是同步序列号,不负责数据传输,设计上就不允许携带数据。
- 面试场景题:如果三次握手的第三次 ACK 丢失,会发生什么?
核心解析:服务端会超时重发 SYN+ACK(默认重发 5 次,每次超时时间翻倍),直到收到客户端的 ACK;若一直未收到,服务端会释放连接,客户端则会在 SYN_SENT 状态超时后,关闭连接。
★ 四次挥手相关面试题
- 为什么 TCP 断开连接需要四次挥手,而不是三次?
核心解析:TCP 是双向通信,双方的发送通道需要独立关闭。
服务端收到客户端的 FIN(第一次挥手)后,可能还有未传输完的数据,不能立即发送 FIN(无法同时确认关闭请求 + 发起关闭),只能先回复 ACK(第二次挥手),等数据发完后,再发送 FIN(第三次挥手),最后客户端确认(第四次挥手),因此需要四次。
- 什么是 TIME_WAIT 状态?为什么需要等待 2MSL?
核心解析:
-
TIME_WAIT 是客户端第四次挥手后进入的状态,持续时间为 2MSL(MSL:最大报文段生存时间,默认 1 分钟)。
-
目的 1:确保服务端能收到客户端的 ACK(若服务端没收到,会重发 FIN,客户端在 TIME_WAIT 期间能再次回复 ACK)。
-
目的 2:等待网络中所有失效的报文段消失,避免新连接复用端口时,收到历史报文段干扰。
- 面试场景题:服务端出现大量 TIME_WAIT 状态,会有什么问题?怎么解决?
核心解析:
-
问题:TIME_WAIT 会占用端口和系统资源,大量出现会导致端口耗尽,新连接无法建立。
-
解决方案(高频考点):
-
调整内核参数:net.ipv4.tcp_tw_reuse(允许复用 TIME_WAIT 端口)、net.ipv4.tcp_tw_recycle(快速回收 TIME_WAIT 连接)。
-
缩短 TIME_WAIT 时长:调整 net.ipv4.tcp_fin_timeout(默认 60s,可适当缩短)。
-
采用长连接(keep-alive),减少频繁建立/断开连接。
- 为什么服务端断开连接后是直接 CLOSED,而客户端要进入 TIME_WAIT?
核心解析:客户端是主动发起关闭的一方,需要负责确认服务端的 FIN 已被收到;服务端是被动关闭的一方,收到客户端的 ACK 后,确认所有数据已传输完成,无需等待,可直接关闭。
四、记忆口诀(面试快速回忆)
-
三次握手:你能发 → 我能收发 → 你能收(同步序列号,确认双方能力)
-
四次挥手:我发完了 → 收到 → 我也发完了 → 收到(双向关闭,确保数据传完)