WebSocket原理#
一句话答案#
WebSocket 基于 HTTP 升级握手后保持全双工长连接,服务端可主动推送,适合聊天/实时通知/行情推送。
核心要点
握手(RFC 6455,HTTP/1.1): 客户端发 GET,带 Upgrade: websocket、Connection: Upgrade、Sec-WebSocket-Version: 13、随机 Sec-WebSocket-Key → 服务端回 101 Switching Protocols,Sec-WebSocket-Accept = Base64(SHA-1(Key + 固定 GUID)),证明服务端真的理解 WebSocket(不是安全认证)
帧格式: 帧头 2~14 字节:FIN 位(消息分片)+ opcode(文本 0x1 / 二进制 0x2 / 关闭 0x8 / ping 0x9 / pong 0xA)+ MASK 位 + 负载长度(7 位,或扩展 16/64 位);客户端发往服务端的帧必须用 4 字节掩码,防止中间代理缓存投毒
HTTP/2、HTTP/3 上的 WebSocket: RFC 8441 用扩展 CONNECT(:protocol: websocket)在一条 HTTP/2 流上跑 WebSocket,不再独占 TCP 连接;HTTP/3 对应 RFC 9220。浏览器 API 不变
vs HTTP: 全双工(服务端可主动推) / 长连接 / 开销小(无HTTP头重复)
适用: 聊天/实时通知/协同编辑/行情推送
面试回答(2分钟版)
WebSocket是一种在单个TCP连接上实现全双工通信的协议,解决了HTTP只能客户端发起请求的限制,让服务端可以主动向客户端推送数据。建立过程是先通过HTTP发起一次握手,请求头带上Upgrade: websocket,服务端返回101 Switching Protocols后就完成了协议升级,之后双方就在这条TCP连接上用WebSocket帧格式双向通信。相比HTTP轮询,WebSocket的优势很明显:全双工所以服务端可以主动推送,不需要客户端反复发请求;长连接复用所以没有反复建连的开销;数据帧头很小没有HTTP那些重复的头信息。典型的应用场景包括即时聊天、实时通知、协同编辑、股票行情推送等需要实时性的场景。不过对于只需要服务端单向推送的简单场景,SSE(Server-Sent Events)更轻量,基于HTTP就能实现,不需要额外的协议升级。实际使用中还需要考虑断线重连和心跳保活机制。
追问与易错
追问方向:
- “WebSocket 和 HTTP 长轮询区别?”→ 长轮询是客户端反复发 HTTP 请求等响应(半双工、开销大),WebSocket 是一次握手后全双工通信(帧头小、服务端主动推送)
- “WebSocket 断线重连怎么做?”→ 客户端监听 onclose 事件后指数退避(加随机抖动)重连 + 应用层心跳(浏览器 JS API 不能主动发 ping 帧,一般自定义 ping/pong 消息;协议层 ping/pong 帧由服务端或浏览器自动处理)+ 重连后带上最后收到的消息序号,让服务端补发缺失消息(lastEventId 是 SSE 的机制,WebSocket 没有,要自己实现)
- “WebSocket 和 SSE 怎么选?”→ SSE 基于 HTTP 单向推送(服务端→客户端),轻量易用自动重连;WebSocket 全双工适合需要双向通信的场景(聊天/游戏)
易错点:
- ❌ WebSocket 就是 HTTP——独立协议只是借 HTTP 握手
- ❌ WebSocket 适合所有实时场景——简单的用 SSE 更轻量