一、WebSocket 是什么?解决了什么问题?
定义:WebSocket 是 HTML5 中定义的双向、全双工通信协议,基于 TCP 实现,允许客户端与服务器建立持久连接,数据可双向主动传输。
解决的痛点:
- HTTP 轮询的低效性:传统 Web 应用通过定时请求(如 AJAX 轮询)获取更新,存在“请求-响应” overhead 和实时性差的问题;
- 单向通信限制:HTTP 协议中服务器无法主动向客户端推送数据,需客户端主动请求。
二、WebSocket 核心原理:握手与通信流程
1. 握手阶段(建立连接)
本质:基于 HTTP 协议完成 WebSocket 协议升级(Upgrade)。
// 客户端请求(WebSocket 握手)
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== // 随机 Base64 字符串
Sec-WebSocket-Version: 13
// 服务器响应(握手成功)
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= // 服务器对 Key 加密后的结果
关键点:
- 协议升级标志:
Upgrade: websocket
和Connection: Upgrade
告知服务器切换协议; - 密钥验证:服务器通过
Sec-WebSocket-Key
验证请求合法性,防止跨域攻击; - 状态码 101:表示协议切换成功,后续通信不再使用 HTTP 协议。
2. 数据传输阶段(全双工通信)
通信模型:建立在 TCP 连接上的双向数据流,客户端与服务器可随时主动发送数据。
帧结构(Frame):
WebSocket 数据以帧为单位传输,帧结构如下(二进制格式):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+---------------------------------------------------------------+
- 关键字段:
opcode
:标识帧类型(如文本帧 0x01、二进制帧 0x02、关闭连接帧 0x08);mask
:客户端发送的帧必须设置mask=1
,服务器无需(防止跨站点WebSocket劫持);payload
:实际传输的数据,支持分片(大文件可拆分为多个帧传输)。
3. 连接关闭阶段
- 主动关闭:客户端或服务器可发送
关闭帧(opcode=0x08)
,携带状态码(如 1000 正常关闭、1006 异常断开)和可选原因; - 被动关闭:若连接超时、网络断开或收到非法帧,会触发异常关闭;
- 状态码意义:
1000
:正常关闭;1001
:服务器/客户端离开(如浏览器关闭);1003
:不支持的数据类型;1006
:未收到关闭帧的异常断开(如网络中断)。
三、WebSocket 与 HTTP 的核心区别
维度 | HTTP | WebSocket |
---|---|---|
连接性质 | 短连接(请求-响应后关闭) | 长连接(一次握手后持续保持) |
通信方向 | 单向(客户端→服务器) | 双向(全双工) |
协议层级 | 应用层协议 | 应用层协议(基于 TCP) |
头部开销 | 每次请求需携带完整头部 | 握手后头部精简(仅包含帧信息) |
数据格式 | 文本为主(JSON/XML) | 支持文本/二进制,帧结构更高效 |
推送能力 | 无(需客户端主动请求) | 支持服务器主动推送 |
四、问题
1. 问:WebSocket 如何实现心跳机制?有什么作用?
答:
- 实现方式:
- 客户端定时发送 ping 帧(opcode=0x09);
- 服务器收到后回复 pong 帧(opcode=0x0A);
- 若客户端未在超时时间内收到 pong,判定连接断开并尝试重连。
- 作用:
- 检测网络连接状态(防止长连接被中间节点(如路由器)断开);
- 维持连接活跃性(避免被防火墙视为“死连接”而关闭)。
2. 问:WebSocket 如何处理断线重连?有哪些策略?
答:
- 重连策略:
- 定时重连:断开后固定时间(如 5s)尝试重连;
- 指数退避重连:首次重连间隔 1s,失败后间隔翻倍(1s→2s→4s…),避免频繁重连占用资源;
- 最大重连次数:设置上限(如 10 次),超过则提示用户手动刷新。
- 状态管理:重连时需记录未完成的消息,确保数据不丢失。
3. 问:WebSocket 如何解决跨域问题?
答:
- WebSocket 握手阶段通过
Origin
字段标识客户端来源,服务器可在响应头中通过Sec-WebSocket-Origin
控制跨域:- 若允许跨域,服务器正常返回握手响应;
- 若拒绝,返回 403 错误或不响应握手请求。
- 与 HTTP 跨域不同,WebSocket 不依赖
Access-Control-Allow-Origin
头,而是在握手层自主控制。
4. 问:WebSocket 在海量连接场景下的性能瓶颈及优化?
答:
- 瓶颈:
- 服务器资源消耗(每个连接占用一个文件描述符,内存开销大);
- 线程模型限制(传统线程池处理大量连接时上下文切换开销高)。
- 优化方案:
- 使用高性能 Web 服务器:如 Nginx 作为反向代理,Node.js 或 Go 语言处理 WebSocket(事件驱动模型);
- 连接分片与负载均衡:按用户 ID 哈希分配到不同服务器,避免单点压力;
- 心跳优化:对活跃连接和非活跃连接设置不同心跳间隔;
- 二进制传输:避免文本序列化开销,直接传输二进制数据(如 Protocol Buffers)。
五、总结
握手基于 HTTP 升级,全双工靠帧传输;
心跳防断连,重连讲策略,跨域看 Origin;
对比 HTTP 抓核心:长连接、双向通、低开销。