前端面试必考:TCP三次握手四次挥手深度解析与实战追问

发布时间:2026/10/18 1:40:57
前端面试必考:TCP三次握手四次挥手深度解析与实战追问 1. 面试官问握手挥手到底在考察什么面过前端的人大概都有这种体验简历上写着熟悉网络基础面试官张口就是“说说三次握手”。很多人背得滚瓜烂熟SYN、ACK、seq、ack 一顿输出结果面试官追问一句“为什么不能是两次”当场卡壳。问题不在于记性不好而在于从一开始就没搞清楚这道题到底在考什么。TCP 的三次握手和四次挥手表面上是背概念实际上是面试官在验证三件事你知不知道连接是怎么建立的、你理不理解可靠传输的代价、你能不能用这套逻辑去解释真实遇到的网络问题。前端岗位问这个不是要你去写协议栈而是因为页面加载慢、接口偶发失败、WebSocket 断连这些日常问题根子经常就在连接的建立和释放上。我见过太多候选人把三次握手背成顺口溜但问他“前端什么时候会触发握手”答不上来。这就暴露了一个问题知识是孤立的没有和自己的工作场景挂钩。所以这篇内容我不打算只给你一份背诵材料而是把这条链路拆开讲清楚每一步为什么存在、前端在哪些环节会碰到它、面试被追问时怎么答才显得是真懂而不是真背。适合谁看准备前端面试的同学、想补网络基础的开发者、以及那些背了但总感觉没吃透的人。下面从连接建立讲起一路讲到挥手、状态机、常见追问最后说说怎么梳理成自己能讲出来的东西。2. 三次握手把“可靠连接”这件事拆开看2.1 握手之前双方其实都是“裸奔”状态要理解握手先得理解握手之前发生了什么。客户端和服务端在建立连接之前彼此没有任何共享信息客户端不知道服务端能不能收、服务端不知道客户端能不能发、双方都不知道对方的初始序列号是多少。而 TCP 是一个面向连接的、可靠的、基于字节流的协议它要保证数据不丢、不重、不乱序那就必须先解决一个前提——双方得先确认彼此都在线并且协商好从哪个字节开始编号。这里有个容易被忽略的点TCP 的可靠性不是靠“连接”这个抽象概念实现的而是靠序列号、确认号、重传机制这些具体手段。握手的过程本质上就是双方交换初始序列号ISN并确认对方收到了自己的序列号。你可以把它想象成两个人打电话前先对暗号我说一句“我要开始说了我从第 100 句开始”你回一句“收到我从第 200 句开始”我再回一句“好的收到你的 200”。这三句话说完双方才敢正式开聊。为什么初始序列号不能固定从 0 或 1 开始这是安全层面的考虑。如果每次连接的起始序列号都可预测攻击者就能伪造报文注入数据。所以现代 TCP 实现里ISN 是根据时钟和一个随机因子算出来的每次连接都不一样。这一点面试时如果被问到“ISN 为什么是随机的”能答上来会加分。2.2 三次握手的每一步到底在交换什么把过程拆成三步来看每一步都有明确的目的不是凑数。第一步客户端发送 SYN 报文携带自己的初始序列号 seqx同时进入 SYN_SENT 状态。这一步的含义是“我想跟你建立连接我的起始编号是 x。”注意此时客户端还不能发数据因为连接还没建立。第二步服务端收到 SYN 后回复一个 SYNACK 报文携带自己的初始序列号 seqy以及确认号 ackx1进入 SYN_RCVD 状态。这一步同时做了两件事确认收到了客户端的 SYNackx1并告诉客户端自己的起始编号seqy。第三步客户端收到后再发送一个 ACK 报文acky1seqx1双方进入 ESTABLISHED 状态。这一步的含义是“我收到你的起始编号了连接可以正式用了。”用表格把这三步的关键字段列清楚面试时脑子里有这个表就不会乱步骤方向标志位seqack状态变化第一步客户端→服务端SYNx无CLOSED→SYN_SENT第二步服务端→客户端SYNACKyx1LISTEN→SYN_RCVD第三步客户端→服务端ACKx1y1SYN_SENT→ESTABLISHED服务端 SYN_RCVD→ESTABLISHED这里有个细节值得注意第三步的 seq 是 x1因为 SYN 报文虽然不携带数据但它会消耗一个序列号。同理第二步的 SYN 也消耗一个序列号所以第三步的 ack 是 y1。这个“SYN 占一个序号”的规则是很多人背的时候会忽略的但面试官如果追问“为什么 ack 要加 1”答不上来就露馅了。2.3 为什么两次不够、四次多余这是握手部分最高频的追问必须答得有逻辑而不是靠感觉。先说为什么两次不行。假设只有前两步客户端发 SYN服务端回 SYNACK然后双方就认为连接建立了。问题出在服务端这边——它发完 SYNACK 之后并不知道客户端有没有收到。如果这个报文在网络中丢了客户端会以为连接没建立而服务端却已经进入 ESTABLISHED 状态傻等着客户端发数据。这就造成了双方状态不一致服务端白白占用资源。更严重的是历史连接的问题。假设客户端之前发过一个 SYN因为网络延迟很久才到达服务端服务端回复 SYNACK 后客户端早已放弃。如果只有两次握手服务端收到这个迟到的 SYN 就会直接建立连接然后一直等一个永远不会来的客户端。三次握手的第三步让客户端有机会说“这个连接我不要”从而避免服务端建立无效连接。再说为什么不需要四次。有人会想既然要双向确认那客户端确认服务端、服务端再确认客户端不是要四次吗关键在于第二步把 SYN 和 ACK 合并了。服务端收到 SYN 后确认客户端和发送自己的 SYN 这两件事可以放在同一个报文里完成没必要分两次。所以三次是理论上的最小值要双向交换 ISN 并各自确认最少需要三个报文。面试时如果被问“能不能用四次”可以答逻辑上可以拆成四次但第二步的 ACK 和 SYN 没有必须分开的理由合并后效率更高所以标准实现是三次。2.4 前端在哪些场景会真实触发握手很多人觉得握手离前端很远其实不然。每一次新的 TCP 连接建立背后都有一次握手。前端常见的触发场景包括首次访问页面时浏览器和服务器建立 HTTP 连接底层就是 TCP 握手。如果是 HTTPS握手之后还有 TLS 握手所以 HTTPS 比 HTTP 慢的那部分一部分就花在这里。使用 WebSocket 建立长连接时先走一次 TCP 握手再走 HTTP 升级协议。页面里请求了不同域名的资源每个新域名都可能触发新的 TCP 连接除非复用了连接池。使用 fetch 或 XMLHttpRequest 发起跨域请求时如果触发了预检请求也可能涉及新连接的建立。理解这一点你就能解释为什么“减少域名数量”“使用连接复用”“开启 HTTP/2”这些优化手段有效——它们本质上都在减少握手的次数。面试时如果能主动把握手和性能优化联系起来比单纯背流程高一个层次。3. 四次挥手为什么断开比建立更麻烦3.1 挥手为什么是四次而不是三次连接建立时SYN 和 ACK 可以合并但断开时ACK 和 FIN 通常不能合并这是四次挥手的根本原因。TCP 是全双工的意味着双方可以同时发送数据。当一方想关闭连接时它只能保证自己不再发数据了但对方可能还有数据没发完。所以关闭必须分方向进行一方发 FIN 表示“我没数据要发了”对方回 ACK 表示“知道了”但对方可能还要继续发数据等它也没数据了再发一个 FIN这边再回一个 ACK。这样就是四次。具体流程第一步主动关闭方假设是客户端发送 FIN 报文sequ进入 FIN_WAIT_1 状态。含义是“我的数据发完了”。第二步服务端收到 FIN回复 ACKacku1进入 CLOSE_WAIT 状态。此时客户端进入 FIN_WAIT_2。注意服务端此时还可以继续发送数据客户端也还能接收。第三步服务端数据发完后发送 FIN 报文seqwacku1进入 LAST_ACK 状态。含义是“我也发完了”。第四步客户端收到 FIN回复 ACKackw1进入 TIME_WAIT 状态。服务端收到后进入 CLOSED。步骤方向标志位seqack状态变化第一步客户端→服务端FINu无ESTABLISHED→FIN_WAIT_1第二步服务端→客户端ACKvu1ESTABLISHED→CLOSE_WAIT客户端→FIN_WAIT_2第三步服务端→客户端FINwu1CLOSE_WAIT→LAST_ACK第四步客户端→服务端ACKu1w1FIN_WAIT_2→TIME_WAIT服务端→CLOSED同样注意 FIN 也消耗一个序列号所以 ack 要加 1。3.2 TIME_WAIT 状态那个让人又爱又恨的 2MSL四次挥手里最常被追问的就是 TIME_WAIT。客户端发完最后一个 ACK 后不会立刻关闭而是进入 TIME_WAIT 状态等待 2MSLMaximum Segment Lifetime报文最大生存时间后才真正关闭。Linux 上这个值通常是 60 秒。为什么要等两个原因。第一保证最后一个 ACK 能到达服务端。如果这个 ACK 丢了服务端会超时重传 FIN此时客户端如果已经关闭就无法回应服务端会一直重试。有了 TIME_WAIT客户端还能收到重传的 FIN 并再次发送 ACK。第二让本次连接的所有报文在网络中消散。如果立刻用相同的四元组建立新连接旧连接中延迟的报文可能被新连接误收造成数据错乱。等待 2MSL 后旧报文基本都消失了。TIME_WAIT 过多是服务端常见的性能问题但要注意TIME_WAIT 通常出现在主动关闭方。如果是服务端主动关闭连接大量 TIME_WAIT 会占用端口资源。前端开发虽然不直接管服务端但面试时如果被问到“大量 TIME_WAIT 怎么办”能说出“让客户端主动关闭”“调整内核参数”“使用连接复用”这些方向就说明你理解了这个状态的本质。3.3 CLOSE_WAIT 堆积前端也可能踩的坑相比 TIME_WAITCLOSE_WAIT 更值得前端警惕。CLOSE_WAIT 出现在被动关闭方含义是“我收到了对方的 FIN但我还没发自己的 FIN”。如果这个状态大量堆积说明程序收到了关闭请求却没有正确关闭连接。前端在 Node.js 服务端渲染、BFF 层、或者用 Node 写中间层时如果代码里打开了 socket 或数据库连接却没有在合适时机关闭就可能出现 CLOSE_WAIT 堆积。表现是连接数越来越多最终耗尽文件描述符服务不可用。排查思路用netstat或ss命令查看连接状态分布如果 CLOSE_WAIT 数量持续增长基本可以定位到代码里某处没有调用 close。常见原因是异常分支没有释放连接、或者回调里忘记关闭。这个经验在面试时讲出来比背状态机图有说服力得多。3.4 半关闭与连接复用的取舍TCP 支持半关闭即一方关闭发送方向但保留接收方向。四次挥手的前两步之后服务端进入 CLOSE_WAIT此时客户端处于 FIN_WAIT_2连接处于半关闭状态。这个机制允许服务端在客户端不再发送数据后继续把剩余数据发完。但实际工程中半关闭用得并不多。HTTP/1.1 默认使用持久连接连接不会频繁关闭HTTP/2 更是多路复用一条连接上跑很多请求。所以挥手发生的频率比握手低。不过理解半关闭有助于解释一些边界问题比如为什么有些服务在收到 FIN 后还能返回数据。面试时如果被问“HTTP 连接什么时候关闭”可以答HTTP/1.0 默认每次请求后关闭HTTP/1.1 默认持久连接由 Connection 头控制服务端或客户端都可以主动关闭。关闭时走的就是四次挥手。4. 状态机与异常面试官真正想听的深度4.1 把状态迁移串成一条线零散地背状态很容易忘串成一条线就清晰了。客户端视角CLOSED → SYN_SENT → ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT → CLOSED。服务端视角CLOSED → LISTEN → SYN_RCVD → ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED。注意服务端有一个 LISTEN 状态这是被动打开时特有的。客户端是主动打开所以没有 LISTEN。面试时如果被问“服务端在握手前处于什么状态”答 LISTEN 就对了。还有一个容易混淆的点同时打开和同时关闭。同时打开时双方都发 SYN状态迁移会变成 SYN_SENT → SYN_RCVD → ESTABLISHED需要四次报文。同时关闭时双方都发 FIN会进入 CLOSING 状态。这些属于偏门但能体现深度的问题了解即可不必死记。4.2 SYN 洪泛与握手的安全维度三次握手有一个天然弱点服务端收到 SYN 后就要分配资源并进入 SYN_RCVD但此时连接还没完全建立。攻击者可以伪造大量源 IP 发送 SYN服务端回复 SYNACK 后收不到第三次 ACK就会一直重试直到超时。这就是 SYN 洪泛攻击。防御手段常见的有 SYN Cookie服务端不立即分配资源而是把状态编码进序列号里收到第三次 ACK 时再重建。还有缩短 SYN_RCVD 的超时时间、限制半连接队列长度等。前端面试一般不会深挖到这个层面但如果聊到网络安全能提一句“三次握手的资源分配时机是 SYN 洪泛的根源”会显得知识面更广。注意这里只谈技术原理不涉及任何具体攻击工具或操作。4.3 抓包验证把理论变成看得见的东西光背不练面试时容易心虚。建议自己用抓包工具跑一遍亲眼看看三次握手和四次挥手的报文。Wireshark 是最常用的工具抓取本机回环接口或者访问一个 HTTP 站点过滤tcp.flags.syn 1就能看到握手过程。抓包时重点观察几个字段Flags 里的 SYN、ACK、FIN 标志Seq 和 Ack 的数值变化以及每次报文的时间戳。你会发现握手通常在一瞬间完成而挥手可能因为服务端还有数据要发而间隔较长。这种直观感受是背书给不了的。如果面试时能说“我自己抓包看过第三次握手的 ACK 里 seq 是 x1”面试官会认为你是真的动手验证过。这比任何背诵都有说服力。5. 高频追问与容易翻车的地方5.1 那些看似简单却容易答错的追问整理几个我见过的高频追问以及容易踩的坑追问常见错误回答正确思路第三次握手可以携带数据吗不可以可以。第三次握手时客户端已进入 ESTABLISHED可以携带数据但通常不这么做第二次握手可以携带数据吗可以不可以。服务端此时还在 SYN_RCVD未完全建立连接握手过程中可以传输数据吗不能前两次不能第三次可以为什么 ISN 要随机不知道防止序列号被预测导致数据注入TIME_WAIT 为什么是 2MSL 不是 1MSL背的1MSL 只能保证一个方向报文消散2MSL 保证往返两个方向这些追问的共同点是它们考察的不是记忆而是你对机制的理解。比如“第三次握手能不能带数据”如果你理解状态迁移就知道客户端发第三次 ACK 时已经进入 ESTABLISHED理论上可以带数据。但实际实现中为了简单和安全通常不带。5.2 把握手挥手和前端性能优化挂钩面试时如果能把基础知识和实际优化联系起来层次立刻不一样。举几个例子减少 TCP 连接数可以降低握手开销所以 HTTP/2 的多路复用比 HTTP/1.1 的多个连接更高效。使用 CDN 时客户端和边缘节点的握手延迟比回源小所以静态资源加载更快。WebSocket 建立后保持长连接避免了反复握手适合实时通信场景。预连接preconnect和 DNS 预解析dns-prefetch能提前完成握手和 DNS 查询缩短关键路径。这些点不需要全部答出来挑一两个结合项目经历讲效果最好。比如“我之前做过一个实时聊天功能用 WebSocket 替代轮询就是因为轮询每次都要新建连接握手开销太大”。5.3 面试表达怎么讲才不像背的最后说表达技巧。背出来的答案有一个特征语速均匀、没有停顿、像念课文。而真正理解的答案会有轻重缓急会主动解释“为什么”。建议的讲法是先一句话概括流程再挑一个关键点深入最后联系实际。比如“三次握手就是双方交换初始序列号并确认的过程。我觉得最关键的是第三步它让客户端有机会拒绝服务端建立的无效连接这也是为什么两次不够。实际中我们做性能优化时减少连接数就是在减少这个过程。”这样的回答有结构、有重点、有落地面试官一听就知道你不是临时抱佛脚。6. 自己梳理一遍比背十遍都管用回到标题里那句话结尾总结建议自己梳理全文背诵。我的理解是梳理在前背诵在后。你得先用自己的话把整条链路讲通再谈记忆。具体怎么做我自己的方法是画一张图把客户端和服务端的状态迁移画成两条平行线中间用箭头标出报文流向。画完之后合上书对着空白纸重新画一遍画不出来的地方就是没掌握的。然后再用抓包工具验证一遍看看真实报文和图上是否一致。还有一个技巧把三次握手和四次挥手对比着记。建立时 SYN 和 ACK 能合并所以三次断开时 ACK 和 FIN 不能合并所以四次。抓住这个差异就不用死记硬背数字了。面试前如果时间紧至少把这几件事过一遍状态迁移图、每一步的 seq 和 ack 变化、TIME_WAIT 的原因、两次不够三次够的理由。这几个点覆盖了八成以上的追问。剩下的深度问题靠平时积累和临场发挥。网络基础这东西背是一时的理解是一辈子的。真正吃透之后你会发现它不只是面试题而是你排查线上问题、做性能优化时的底层直觉。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询