一、WebSocket 详解
1.1 WebSocket 是什么?
-
WebSocket 是一种全双工(full-duplex)通信协议,运行在 TCP 协议之上,旨在解决 HTTP 协议在实时通信场景中的局限性。它允许客户端和服务器建立持久连接后,双向实时传输数据,无需频繁创建新连接,是现代实时 Web 应用的核心技术之一
-
为了兼容现- 有的设施,
WebSocket
协议使用与 HTTP 协议相同的端口, 并使用HTTP Upgrade
机制来进行WebSocket
握手, 当握手完成之后, 通信双方便可以按照WebSocket
协议的方式进行交互。 -
需要特别注意的是:虽然
WebSocket
协议在建立连接时会使用HTTP协议,但这并意味着WebSocket
协议是基于HTTP协议实现的。
1.2 WebSocket 的特点
-
持久连接:一旦握手成功,连接会保持打开状态,避免 HTTP 反复建立 / 断开连接的开销。
-
全双工通信:客户端和服务器可同时向对方发送数据,打破 HTTP “请求 - 响应” 的单向模式限制。
-
低开销:数据帧头部较小(最小 2 字节),远低于 HTTP 头部(通常数百字节),节省带宽。
-
基于 TCP:依赖 TCP 的可靠性(有序、无丢失),但自身不提供重传机制(由 TCP 底层保证)。
-
协议标识符:使用
ws://
(非加密)和wss://
(加密,基于 TLS)作为 URI 前缀,默认端口分别为 80 和 443。
1.2 WebSocket的协议格式
WebSocket 通信分为握手阶段和数据传输阶段,两者格式不同。
1.2.1 握手阶段
WebSocket 握手是 “升级” HTTP 连接的过程,依赖 HTTP 协议完成初始协商:
- 客户端请求:发送 HTTP GET 请求,携带
Upgrade: websocket
和Connection: Upgrade
头部,表明要切换到 WebSocket 协议,同时包含随机生成的Sec-WebSocket-Key
(用于服务器验证)。
示例:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
- 服务器响应:返回 HTTP 101(Switching Protocols)状态码,确认协议切换,同时通过
Sec-WebSocket-Accept
头部返回Sec-WebSocket-Key
加密后的结果(验证客户端合法性)。
示例:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
1.2.2. 数据传输阶段
WebSocket 数据以 “帧(Frame)” 为单位传输,每帧格式如下(二进制结构):
字段 | 长度(bit) | 含义 |
---|---|---|
FIN | 1 | 是否为消息的最后一帧(1 = 是,0 = 否,用于分片传输大消息)。 |
RSV1~RSV3 | 1*3 | 保留位,用于扩展协议(默认必须为 0,非 0 需双方协商扩展)。 |
Opcode | 4 | 帧类型: - 0x0:延续帧(分片消息的中间帧) - 0x1:文本帧(UTF-8 编码) - 0x2:二进制帧 - 0x8:关闭连接帧 - 0x9:Ping 帧(心跳检测) - 0xA:Pong 帧(响应 Ping) |
Mask | 1 | 是否对 payload 加密(1 = 是,仅客户端发送的帧需要掩码,服务器发送的帧不掩码)。 |
Payload Length | 7/7+16/7+64 | payload 数据长度: - 0~125:直接表示长度 - 126:后续 2 字节表示长度(16 位无符号整数) - 127:后续 8 字节表示长度(64 位无符号整数) |
Masking-Key | 0/32 | 掩码密钥(仅当 Mask=1 时存在,32 位随机数,用于解密 payload)。 |
Payload Data | 可变 | 实际传输的数据(文本 / 二进制 / 控制信息)。 |
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 ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
举例:
- 客户端发送的文本帧(传输字符串 “Hello”),客户端发送的帧必须带掩码(
Mask=1
),假设传输内容为 UTF-8 字符串 “Hello”(5 字节):
字节偏移 | 十六进制值 | 对应字段解析 |
---|---|---|
0 | 0x81 | FIN=1 (最后一帧),RSV1~3=000 (无扩展),Opcode=0x1 (文本帧) |
1 | 0x85 | Mask=1 (客户端帧必须掩码),Payload Length=5 (数据长度为 5 字节) |
2-5 | 0x37 0xFA 0x21 0x3D | 32 位掩码密钥(随机生成) |
6-10 | 0x48 0x65 0x6C 0x6C 0x6F | 掩码处理后的 payload 数据(原始数据 “Hello” 经掩码加密后结果) |
解析:
FIN=1
:表示这是完整消息(非分片)。Opcode=0x1
:明确是文本帧(内容为 UTF-8 编码)。- 掩码处理:客户端用 32 位掩码密钥对原始数据逐字节异或(
data[i] ^= mask[i%4]
),服务器接收后需用相同密钥解密。
例如原始数据 “H”(0x48)与掩码第 0 字节(0x37)异或:0x48 ^ 0x37 = 0x7F
?实际计算需根据具体掩码,此处仅为示例结构。
- 服务器发送的二进制帧(传输 3 字节二进制数据 0x01 0x02 0x03),服务器发送的帧不需要掩码(
Mask=0
):
字节偏移 | 十六进制值 | 对应字段解析 |
---|---|---|
0 | 0x82 | FIN=1 ,RSV1~3=000 ,Opcode=0x2 (二进制帧) |
1 | 0x03 | Mask=0 (服务器帧不掩码),Payload Length=3 (数据长度 3 字节) |
2-4 | 0x01 0x02 0x03 | 原始二进制数据(无需掩码处理,直接传输) |
解析:
Opcode=0x2
:表示二进制帧(可传输任意字节流,如图片、protobuf 数据等)。- 无掩码:服务器发送的帧
Mask
必须为 0,客户端接收后直接使用 payload 数据。
1.3 WebSocket 的应用场景
WebSocket实现了客户端与服务器的实时双向通信,解决传统 HTTP 方案(如轮询、长轮询)的效率问题:
- 替代 “轮询”:避免客户端频繁发送 HTTP 请求(如每秒一次)导致的带宽浪费和延迟。
- 支持实时推送:服务器可主动向客户端发送数据(如消息通知、实时数据更新),无需客户端先请求。
应用场景:
-
即时通讯:聊天应用(如微信网页版、Discord),支持用户间实时消息收发。
-
实时协作工具:在线文档(如腾讯文档、Notion),多人编辑时实时同步内容变更。
-
在线游戏:实时对战游戏(如多人棋牌、MOBA 网页版),同步玩家操作和游戏状态。
-
实时监控:物联网设备监控(如智能家居状态推送)、系统监控仪表盘(实时显示 CPU / 内存数据)。
-
金融数据推送:股票行情、加密货币价格实时更新(毫秒级推送)。
-
直播互动:直播间弹幕、礼物特效实时展示,观众与主播互动。
1.4 WebSocket和HTTP对比
-
WebSocket是双向通信模式,客户端与服务器之间只有在握手阶段是使用HTTP协议的“请求-响应”模式交互,一旦连接建立之后的通信则使用双向模式交互,不论是客户端还是服务端都可以随时将数据发送给对方
-
HTTP协议则至始至终都采用“请求-响应”模式进行通信,通信效率没有WebSocket高。
- HTTP协议比较臃肿,而WebSocket协议比较轻量:对于HTTP协议来讲,一个数据包就是一条完整的消息,而WebSocket客户端与服务端通信的最小单位是帧(frame),由1个或多个帧组成一条完整的消息(message),发送端将消息切割成多个帧,并发送给服务端,服务端接收消息帧,并将关联的帧重新组装成完整的消息。
特性 | HTTP | WebSocket |
---|---|---|
连接方式 | 短连接(请求 - 响应后断开) | 长连接(一次握手后持久保持) |
通信方向 | 单向(客户端请求→服务器响应) | 双向(客户端↔服务器同时发送) |
头部开销 | 大(数百字节,含 Cookie 等) | 小(数据帧头部仅 2~14 字节) |
实时性 | 低(依赖轮询间隔) | 高(毫秒级延迟) |
适用场景 | 静态资源获取、非实时接口 | 实时交互、推送场景 |