大三面字节被问懵?手撕 WebSocket 与 SSE 底层原理,大厂通关指南

俗话说得好:"面试造火箭,工作拧螺丝"。但如果你连长连接的底层协议都搞不清楚,可能连进大厂拧螺丝的资格都没有。

昨天,隔壁寝室的哥们面字节暑期实习,直接被一道 408 场景题干得汗流浃背: "做过 Chat App 是吧?那你说说 WebSocket 和 SSE 有什么区别?接 DeepSeek 的流式输出该用哪个?"

很多同学平时写业务天天 npm install 调包,遇到网络层的问题直接"阿巴阿巴"。但在这个 AI 大模型全网刷屏的时代,长连接和流式输出早就成了前端和 Node.js 圈的绝对高频考点

作为一名见不得"屎山代码"的大三党,今天学弟就带大家抓个包,把 HTTP 轮询、WebSocket 和 SSE 的底层逻辑扒个底朝天。建议先 ⭐ 收藏,面试前拿出来背一遍,绝对让面试官对你刮目相看!


🤡 为什么说 HTTP 轮询是"外包级"方案?

假设现在需求是做一个在线聊天室。新手最爱干的事,就是写个 setInterval(),每隔 3 秒发个 Ajax 请求去问服务器:"大佬,有新消息吗?"

⚠️ 前方高能:这是典型的史诗级灾难写法! HTTP 是一个无状态、单向的短连接(Request-Response 模型)。你每次轮询,都要重新建立 TCP 连接(即使有 Keep-Alive 也会有巨大开销),还要带上一大堆臃肿的 HTTP Header。

打个通俗的比方:HTTP 就像是**"寄信"**。用轮询做聊天室,就像是你每隔 3 秒就去狂敲邮局的门问:"有我的信吗?"------不仅你累,服务器也得被你烦死,人一多直接原地宕机。


🚀 降维打击:WebSocket 的全双工魔法

为了终结这种愚蠢的轮询,HTML5 推出了 WebSocket 协议。这玩意儿一上来,直接把"寄信"跨时代地升级成了**"打电话"**。只要电话一接通,双方就可以毫无阻碍地互发消息。

Talk is cheap,我们先看一眼用 Koa 撸一个 WebSocket 服务器有多优雅:

JavaScript

dart 复制代码
const Koa = require('koa'); 
const websocket = require('koa-websocket');

// 注入 WebSocket 能力
const app = websocket(new Koa());
const clients = new Set(); // 维护客户端连接池

// 处理 WebSocket 长连接逻辑
app.ws.use(async (ctx, next) => {
    clients.add(ctx.websocket); // 用户上线
    
    // 服务端接收到消息时,广播给所有人(群聊核心逻辑)
    ctx.websocket.on('message', message => {
        for (const client of clients) {
            client.send(message.toString());   
        }
    })
    
    // 划重点:断开连接时必须清理内存,否则会导致内存泄漏!
    ctx.websocket.on('close', () => {
        clients.delete(ctx.websocket);
    })
})

app.listen(3000);

代码很简单,但面试官真正在意的是下面这两个底层护城河

💀 硬核揭秘 1:抓包看 101 协议升级 的密码学验证

面试官发难:"WebSocket 建立连接时发的是 HTTP 请求吗?"

拔掉网线,打开 Wireshark 或者 Network 面板抓个包,你会发现第一次握手的 Header 里藏着玄机:

HTTP

makefile 复制代码
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

看到这个 Sec-WebSocket-Key 了吗?服务端收到这串随机的 Base64 字符后,必须做一套极其严格的规范动作:

  1. 把这个 Key 与一个全球通用的魔法字符串258EAFA5-E914-47DA-95CA-C5AB0DC85B11)拼接。
  2. 进行 SHA-1 运算,再转成 Base64,生成 Sec-WebSocket-Accept 返回给客户端。

为什么要这么折腾?防黑客吗? 错!明文传输防个锤子。这是为了防止无意的**"缓存投毒" (Cache Poisoning)**,并且让客户端确认:"对面这台服务器是真的懂 WebSocket 协议,而不是碰巧返回了 200 OK"。

💀 硬核揭秘 2:为什么 WS 能发图片,而 HTTP 只能发文本?

WebSocket 传输的数据不叫报文,叫**"数据帧(Frame)"**。协议底层定义了一个 4 bit 的 Opcode(操作码)

  • Opcode = 0x1:浏览器知道这是一串文本
  • Opcode = 0x2:浏览器知道这是一坨二进制流,直接扔给 ArrayBuffer 处理图片或音视频。

这才是它能扛起复杂互动场景(如页游、直播弹幕)的全能底气。


🤖 大模型时代的新宠:SSE (Server-Sent Events)

既然 WebSocket 这么强,那为什么我们用 ChatGPT 或 DeepSeek 时,抓包发现它们根本没用 WebSocket,而是用了 SSE

因为业务场景变了! 大模型的"打字机效果",是一个单向流式输出 的过程。你发一句 Prompt,AI 连续吐出几百个词。这个场景根本不需要全双工双向发消息,只需要服务器单向高频推送即可!

💀 硬核揭秘 3:扒掉 SSE 的外衣,它的底层其实是 Chunked 编码

很多小白把 SSE 当成什么高深的新协议,大错特错!SSE 是 100% 纯正的 HTTP/1.1 协议。

它的核心黑科技,是利用了 HTTP 响应头里的 Transfer-Encoding: chunked(分块传输编码)

HTTP

less 复制代码
Content-Type: text/event-stream
Transfer-Encoding: chunked
Connection: keep-alive

正常的 HTTP 请求必须带 Content-Length,浏览器拿到指定大小的数据就关门大吉。 但加上 chunked 后,服务器的意思是:"我也不知道 AI 要说多少废话,我一块一块(Chunk)发给你吧。"

服务器每次吐出一个字,就按 data: 你好\n\n 的格式发过去。浏览器底层的流处理器只要读到 \n\n,就知道一块数据到了,立刻触发前端的渲染。杀鸡焉用牛刀,处理单向推送,SSE 才是最优雅的神!


🔥 终极避坑:大厂必问的"心跳保活"机制

不管你用 WS 还是 SSE,只要写了"长连接",面试官必放终极杀招: "如果用户进了电梯没信号了,或者直接拔了网线,你的服务器怎么知道他掉线了?"

千万别回答"等 TCP 超时断开"------TCP 底层的 Keep-Alive 默认要两小时才触发,那时候你服务器的连接池早被死链接撑爆了!

正确的做法是在应用层实现心跳机制 (Heartbeat)

  • 常规玩法:客户端定时器每隔 30 秒发一个 JSON 格式的 Ping 消息,服务器回复 Pong。超时未收到回复,前端主动断开并重连。
  • 满分玩法(针对 WebSocket) :利用刚才提到的底层帧结构!WebSocket 协议原生定义了 0x9 (Ping帧)0xA (Pong帧)。在 Node.js 中,你可以直接调用底层的 Ping/Pong 控制帧,连 JSON 序列化的性能损耗都省了,把并发性能压榨到极致!

🎯 总结:没有银弹,只有取舍

架构设计的魅力就在于"看菜下饭":

  1. 联机游戏、协同文档、实时聊天室 👉 毫不犹豫选 WebSocket
  2. 大模型对话、站内单向消息通知 👉 选轻量级、原生兼容 HTTP 的 SSE

技术迭代浩浩荡荡,最后给各位技术大佬留个探讨题:随着 HTTP/2 和 HTTP/3 的普及,它们强大的多路复用和全双工特性,未来会让 WebSocket 退出历史舞台吗?

欢迎在评论区畅所欲言,学弟在线挨打交流!👇

相关推荐
蓝黑20202 小时前
Vue SFC Playground
前端·javascript·vue.js
qq_406176142 小时前
React与Vue异同点及优缺点深度解析
前端·vue.js·react.js
广州华水科技2 小时前
GNSS位移监测技术在基础设施安全中的应用与单北斗变形监测系统的优势解析
前端
Moment2 小时前
不懂模块化就别谈前端工程化
前端·javascript·面试
majingming1239 小时前
FUNCTION
java·前端·javascript
A_nanda10 小时前
Vue项目升级
前端·vue3·vue2
SuperEugene10 小时前
Axios 接口请求规范实战:请求参数 / 响应处理 / 异常兜底,避坑中后台 API 调用混乱|API 与异步请求规范篇
开发语言·前端·javascript·vue.js·前端框架·axios
abigale0311 小时前
【浏览器 API / 网络请求 / 文件处理】前端文件上传全流程:从基础上传到断点续传
前端·typescript·文件上传·vue cli
Setsuna_F_Seiei11 小时前
AI 对话应用之页面滚动交互的实现
前端·javascript·ai编程