🧑💻 面试官:TCP 为什么要三次握手?
🙋♂️ 我:双方要同步初始序号,并确认彼此的连接请求。
🧑💻 面试官:服务端回了 SYN 和 ACK,为什么还要客户端再确认一次?
🙋♂️ 我:否则服务端还不能确认自己的序号已经被对方收到。
🧑💻 面试官:建立时能把两件事合成一包,关闭为什么说四次?ACK 和 FIN 就绝对不能合并吗?
TCP 管的是两个方向的可靠字节流:建立要互相确认序号,关闭则要分别说明两个方向是否还会发送。
面试速答(60 秒版)
TCP 三次握手的核心,是同步双方初始序号,并确认各自发送的 SYN 已经被对方收到。
客户端先发 SYN,服务端用 SYN 加 ACK 既确认客户端,又提出自己的序号,客户端再发 ACK 确认服务端。它不只是检查“网络通不通”,也要避免把迟到的旧请求当成完整的新连接。
关闭时,两个方向可以分别结束。一方发 FIN 表示自己不再发送,对方先确认,但可能还有数据要发;等它也发送 FIN,再由前一方确认,所以常见是四次交互。
不过 ACK 与 FIN 可以合并,不是所有关闭都一定出现四个包。主动关闭的一方通常进入 TIME_WAIT,等待重传的 FIN 并隔开旧连接报文,不能简单说成客户端专属状态。

知识点详解:为什么两个方向要分别确认?
第三次握手到底确认了什么?
假设客户端选择初始序号 x,服务端选择 y。
客户端发 SYN,序号为 x。服务端确认 x,同时用自己的 SYN 提出 y。客户端最后确认 y。SYN 会占用一个序号,所以确认值分别是 x+1 和 y+1。
服务端发出第二步后,只知道自己收到了客户端请求,还不能确认客户端收到了它提出的序号。第三步让这个确认关系补齐。
如果一个旧 SYN 因延迟又到达,服务端可能响应,但在缺少有效后续确认时,不应把它直接当成完成的新连接。序号检查与状态机共同帮助区分这种情况。
三次握手也会协商部分连接参数,但它不是证明对方业务身份的认证协议。能建立 TCP,不代表对方就是可信服务。

四次挥手,实际是在关闭两条发送方向
假设客户端 A 先不再发送,发出 FIN。它表示的是“A 到 B 这个方向没有更多字节了”,不是要求 B 丢掉剩余数据。
B 收到以后发 ACK,A 的关闭意图得到确认。但 B 可能还需要发送已经准备好的响应,因此 A 仍然可以接收。
等 B 也不再发送,再发 FIN,A 确认它,两个发送方向才都完成关闭。这就是常见四次交互的来源。
如果 B 当时也已经准备关闭,可以把对 A 的确认和自己的 FIN 放在一起。因此,“四次挥手”是常见序列的概括,不能当成任何抓包都必须有四个独立报文。异常 RST 关闭也不是这套正常结束过程。
最后一个 ACK 发出以后,为什么还要等?
假设 A 发出最后 ACK,但这个 ACK 丢了,B 会重传 FIN。A 处在 TIME_WAIT 时,还可以对这个 FIN 再做确认。
同时,网络中可能残留旧连接报文。等待一段时间,有助于让旧报文消失,避免干扰后来复用相同连接标识的连接。
TCP 连接通常由双方地址和端口形成四元组。标准中的等待与最大报文生存时间有关,正常主动关闭后的 TIME_WAIT 按 2×MSL 解释,但具体系统时间值与实现策略需要单独核对。RFC 9293定义了这些状态和行为。
这里不能把重传保护与旧报文隔离讲成“服务器忙不过来,所以随便多等一会”。等待属于连接状态管理,不是固定的业务缓冲。

TIME_WAIT 为什么不一定在客户端?
谁先主动关闭,取决于应用行为。服务端先结束连接,它也可能进入相应状态。
同时关闭等路径也会让状态更复杂。因此,分析抓包要看 FIN 顺序和各自状态,不能只看哪一边叫客户端。
对端已经半关闭后,本地应用长时间不关闭,可能出现 CLOSE_WAIT。这与 TIME_WAIT 的正常等待不是同一个问题。排查连接堆积时,先区分状态,比直接修改内核参数更有用。
面试官继续追问
TIME_WAIT 多,应该马上缩短吗?
不应该只看数量。高频短连接本来就可能产生很多 TIME_WAIT。
先确认是否造成端口或连接资源问题,再检查是否可以复用连接、采用连接池和合理的保持连接策略。盲目缩短等待可能改变可靠性边界,不能为了让监控数字好看就修改。
三次握手能保证对方一定在线吗?
只能说明建立阶段完成了相应交互,之后对方仍可能断网或崩溃。
长期连接需要结合应用超时、心跳或其他探测判断。TCP 建立成功,也不能证明一次业务请求最终完成。
连接断开以后,订单请求能不能直接再发?
要看业务是否已经执行。响应没收到,不等于服务端没有创建订单。
需要请求身份和业务幂等机制核对结果。TCP 解决传输,不替应用保证副作用只发生一次。
面试速记卡
- 三次握手:同步双方序号,并互相确认 SYN。
- 正常关闭:两个发送方向分别结束,可以存在半关闭。
- 四次不是硬包数:ACK 与 FIN 可以合并。
- TIME_WAIT:处理最后确认丢失与旧报文,通常跟随主动关闭。
- 应用边界:连接状态不证明业务完成或只执行一次。
