面试记录 2026-09-27
题目:什么是TCP三次握手、四次挥手?
难度:low
标签:computer/network, general/knowledge
评分:⭐⭐☆☆☆(2/5)
我的回答
TCP 通过三次握手和四次挥手,确保了自己可靠性的保证,信息传递的可靠性的保证。
通过三次握手确认发送方与接收方的接收与发送能力。
通过四次挥手来确定消息整个全部结束,再加确认这个事情已经完结。
点评
优点:
- 抓住核心思想:三次握手确认双方收/发能力,四次挥手用于连接释放
- 提到"确认双方收发能力"这个关键点
不足:
- 完全没有说出具体流程:三次握手是哪三次?谁发什么标志(SYN/ACK)?
- 没有讲状态流转:LISTEN / SYN_SENT / SYN_RCVD / ESTABLISHED / FIN_WAIT_1 / FIN_WAIT_2 / CLOSE_WAIT / TIME_WAIT / LAST_ACK 等状态完全没提
- 没解释为什么是三次:为什么两次不够(历史连接)、四次又没必要
- 没解释为什么是四次:TCP 是全双工,双向连接要各自关闭,客户端 FIN 后服务端可能还有数据要发完
- 表述过于口语化,"确认这个事情已经完结"没技术含量
补充:
- 客户端发
SYN, seq=x → SYN_SENT
- 服务端回
SYN+ACK, seq=y, ack=x+1 → SYN_RCVD
- 客户端回
ACK, ack=y+1 → ESTABLISHED(服务端收到也进入 ESTABLISHED)
- 主动方发
FIN → FIN_WAIT_1
- 被动方回
ACK → CLOSE_WAIT,主动方进入 FIN_WAIT_2
- 被动方数据发完后发
FIN → LAST_ACK
- 主动方回
ACK → TIME_WAIT,2MSL 后 CLOSE;被动方收到 ACK → CLOSE
- TIME_WAIT 存在的原因:防止最后一个 ACK 丢失导致被动方重发 FIN,同时确保旧连接的延迟报文在网络中消失
- 为什么 TCP 挥手需要四次:因为连接是全双工,被动方收到 FIN 后可能还有数据没发完,需要独立回 ACK 表示"我知道你要关了"
完整讲解
第一部分:知识重点剖析
核心考点定位:考察 TCP 连接建立与释放的具体报文交换流程、状态机流转,以及设计背后的原因。
知识点拆解:
- 三次握手流程(建立连接):SYN → SYN+ACK → ACK,双方通过交换初始序列号确认彼此的收/发能力。
- 为什么是三次:两次不行——服务端可能重复建立早已失效的历史连接,浪费资源;三次是最少的可靠握手次数(每次交互双方各确认一次收发能力,需要 3 次报文才能完成)。
- 四次挥手流程(释放连接):FIN → ACK → FIN → ACK,被动方需要独立回 ACK 因为它可能还有数据要发完。
- 为什么挥手是四次:TCP 是全双工,双向连接要分别关闭。FIN 表示"我这边没数据要发了",而 ACK 表示"我知道你要关了",两者不能合并(因为 ACK 时可以还有数据待发)。
- TIME_WAIT 与 2MSL:主动关闭方进入 TIME_WAIT 状态等待 2MSL(Linux 默认 60s)。目的是(1)保证最后一个 ACK 到达,若丢失被动方可重发 FIN;(2)让旧连接的延迟报文在网络中自然消亡,避免污染新连接。
- 异常场景:SYN Flood 攻击(半连接队列被打满)、TIME_WAIT 过多(大量短连接导致)、CLOSE_WAIT 堆积(应用层未 close socket 代码 bug)。
递进:握手是"三次因为要确认双向收发",挥手是"四次因为全双工要分开关"。
第二部分:考察方向与延伸递进
考察方向:
- 深度:状态机流转、SYN/FIN/ACK 标志位含义、MSL 定义
- 广度:QUIC 如何把握手和 TLS 合并到 0-1 RTT、HTTP 长连接如何复用 TCP 连接
- 应用:生产环境 TIME_WAIT 过多的排查与调优、SYN Flood 防御
延伸递进面试题:
- 两次握手为什么不行?
- 解答要点:客户端发的 SYN 如果在网络中延迟,服务端以为要建连回 SYN+ACK,客户端不会理睬;服务端却进入 ESTABLISHED 状态浪费资源。三次握手中客户端收到迟到的 SYN+ACK 会回 RST。
- 生产环境大量 TIME_WAIT 怎么办?
- 解答要点:查看
ss -s、netstat -an | grep TIME_WAIT | wc -l;调 sysctl.net.ipv4.tcp_tw_reuse=1(4.12+)复用 TIME_WAIT socket;根本方案是复用连接(HTTP Keep-Alive、连接池)。
- CLOSE_WAIT 堆积说明什么?
- 解答要点:对方已发 FIN 但自己应用未调用 close(),通常是代码 bug 或 socket 未关闭导致的泄漏,需检查应用代码。
- 如何防止 SYN Flood 攻击?
- 解答要点:SYN cookies(
tcp_syncookies=1)、增加半连接队列 tcp_max_syn_backlog、缩短 tcp_synack_retries、用 iptables 限速。
第三部分:面试者参考回答(300-600 字口语化)
面试官您好,TCP 三次握手和四次挥手我分开讲。
三次握手:目的是双向确认彼此的收发能力。
- 第一次:客户端发
SYN, seq=x,进入 SYN_SENT 状态;
- 第二次:服务端回
SYN+ACK, seq=y, ack=x+1,进入 SYN_RCVD,既确认了客户端的 SYN,也把自己的 SYN 发出去;
- 第三次:客户端回
ACK, ack=y+1,进入 ESTABLISHED,服务端收到 ACK 后也进入 ESTABLISHED。
为什么是三次:两次不够,如果客户端的 SYN 在网络中延迟到达,服务端可能建立一条已经没用的连接。三次是"每次交互双方各确认一次"的最小交互次数。
四次挥手:连接是全双工的,要分别关,所以不能像握手那样合起来。
- 第一次:主动方发
FIN,进入 FIN_WAIT_1;
- 第二次:被动方回
ACK,进入 CLOSE_WAIT,主动方进入 FIN_WAIT_2;(这时候被动方可能还有数据要发,所以不能把 FIN 合并到 ACK)
- 第三次:被动方数据发完,发
FIN,进入 LAST_ACK;
- 第四次:主动方回
ACK,进入 TIME_WAIT,等 2MSL 后 CLOSE;被动方收到 ACK 后 CLOSE。
TIME_WAIT 为什么要等 2MSL:一是保证最后一个 ACK 能到达被动方,如果丢了被动方会重发 FIN;二是让旧连接的所有报文都自然消亡,避免污染同一个四元组的新连接。生产上如果 TIME_WAIT 太多,通常意味着大量短连接,可以开启 tcp_tw_reuse 或者复用连接。
CLOSE_WAIT 堆积是另一种异常,说明应用代码没 close socket,通常是 bug。