WebSocket
面试一句话总结:WebSocket 是一种基于 TCP 的全双工、双向通信协议。它借用 HTTP 协议完成一次握手升级(状态码 101),之后便摆脱 HTTP 的束缚,以极低开销的二进制帧进行实时数据传输。常用于聊天室、协同编辑和实时大屏。
1. 核心工作原理
WebSocket 虽然名字里带 Web,但它实际上是一个独立的协议(ws:// 或加密的 wss://),它只是在“建立连接”这个阶段“蹭”了一下 HTTP 的车。
① 协议升级 (HTTP 握手)
建立连接时,客户端会发送一个标准的 HTTP GET 请求,并在请求头中要求“升级协议”:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
服务端如果支持 WebSocket,会返回 101 Switching Protocols 状态码,并计算一个 Sec-WebSocket-Accept 返回给客户端。
至此,HTTP 功成身退,这条 TCP 连接被 WebSocket 正式接管。
② 数据传输格式 (帧 Frame)
与 HTTP 每次请求都携带几百字节的臃肿 Header 不同,WebSocket 传输数据时使用的是帧 (Frame) 格式,帧头极小(通常只有 2~10 个字节)。
它原生支持传输文本(Text)以及二进制数据(ArrayBuffer 和 Blob),非常适合音视频流传输。
2. 与 HTTP 及 SSE 的对比 (高频考点)
在高级面试中,面试官往往会让你对比这几种通信方案的选型。
| 特性 | HTTP (轮询/长轮询) | SSE (Server-Sent Events) | WebSocket |
|---|---|---|---|
| 通信方向 | 半双工 (单向) | 单向 (服务端推给客户端) | 全双工 (双向) |
| 协议层 | HTTP | HTTP | WebSocket (独立协议) |
| 重连机制 | 无 | 浏览器原生支持自动重连 | 需手写心跳保活和断线重连 |
| 头部开销 | 极大 (每次带完整 Header) | 较大 | 极小 (2~10 字节帧头) |
| 适用场景 | 低频数据请求 | AI 打字机、股票大屏、消息通知 | IM 聊天、协同编辑、在线游戏 |
实战选型思考: 如果业务需求只是“服务端向客户端单向推数据”(如 ChatGPT 的回复、系统广播),绝对优先选择 SSE。它更轻量,且原生支持断线重连。只有在需要高频、实时的双向交互时,才动用 WebSocket 这个重型武器。
3. 工程实战与难点解决
如果在简历里写了 WebSocket,面试官一定会问你如何保证连接的稳定性。
① 心跳检测 (Ping/Pong 保活)
痛点:TCP 长连接在长时间没有数据传输时,很容易被中间的网络设备(如 Nginx、防火墙、运营商 NAT)当作死连接而偷偷掐断,此时前端根本感知不到(触发不了 onclose)。
解法:前端需要实现心跳机制。每隔固定的时间(如 30 秒)向服务端发送一个内容为 Ping 的空帧,服务端收到后立刻回复 Pong。如果前端连续几次发了 Ping 却没有收到 Pong,就认为连接已死,主动执行重连。
② 优雅的断线重连 (指数退避算法)
痛点:当服务器宕机或网络抖动导致连接断开时(触发 onclose / onerror),如果几万个客户端同时疯狂重试,会导致服务器瞬间被打挂(类似 DDoS 攻击)。
解法:使用指数退避算法(Exponential Backoff)。重试间隔不是固定的,而是成倍增加(如 1s, 2s, 4s, 8s, 16s...),并且还要加上一段随机抖动时间 (Jitter),打散客户端的重连请求峰值。
③ 身份鉴权问题
痛点:WebSocket 无法像 HTTP 请求那样,利用拦截器在 Header 里方便地带上 Authorization: Bearer Token。
解法:
- URL 传参(最常见但有安全隐患):
ws://api.com?token=xxx。缺点是 Token 容易记录在网关的访问日志中。 - 连接后第一条消息鉴权(最安全):建立连接后,服务端不接受任何业务指令,要求前端先发一条专门的
{"type": "auth", "token": "xxx"}消息。服务端校验通过后才放行,否则直接掐断连接。
4. 安全防护 (WSS)
- WSS 协议:生产环境必须使用
wss://代替ws://。它在 TLS 层上进行了加密(类似于 HTTPS),能有效防止抓包和中间人攻击。 - 跨站 WebSocket 劫持 (CSWSH):类似于 HTTP 的 CSRF 攻击。恶意网站可以通过 JS 直接向你的服务端发起 WebSocket 连接。防范方案:服务端在握手阶段,必须严格校验 HTTP 请求头中的
Origin字段是否在白名单内。