3. WebSocket协议入门

在实时行情系统中,客户端需要持续、低延迟地接收价格、成交量、盘口等推送数据。传统HTTP的“请求—响应”模型天然不适合这种场景,而WebSocket正是为解决双向实时通信而设计的应用层协议。本节从握手、帧结构、全双工特性以及与HTTP轮询、SSE的对比四个角度,建立对WebSocket的系统认知。

一、核心原理:从HTTP升级到独立双向通道

WebSocket并非完全脱离HTTP,而是借助HTTP完成一次“协议升级”握手,之后在同一个TCP连接上切换到WebSocket自己的帧协议。整个生命周期可分为三个阶段:

  1. 握手阶段:客户端发送带有 Upgrade: websocket 的HTTP请求,服务端返回 101 Switching Protocols,双方确认升级。
  2. 数据传输阶段:连接建立后,客户端与服务端可随时互发数据帧,不再遵循“一问一答”。
  3. 关闭阶段:任一方发送关闭帧(Close Frame),另一方回应后关闭TCP连接。

握手请求的关键头部如下,其中 Sec-WebSocket-Key 是客户端随机生成的Base64字符串,服务端需将其与固定GUID拼接后做SHA-1哈希并Base64编码,作为 Sec-WebSocket-Accept 返回,用于校验握手合法性。

GET /market/stream HTTP/1.1
Host: quote.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
握手成功后,后续通信不再使用HTTP语义,而是WebSocket帧。因此抓包时看到101响应之后的数据,需要用WebSocket协议解析,而非HTTP。

二、帧结构:理解数据如何被切分与传输

WebSocket以“帧”为最小传输单位。一个消息可能由一个或多个帧组成,帧头固定为2字节起,包含以下关键字段:

  • FIN:标识是否为消息的最后一帧,支持分片传输大消息。
  • Opcode:帧类型,如 0x1 文本、0x2 二进制、0x8 关闭、0x9 Ping、0xA Pong。
  • Mask:客户端发往服务端的帧必须掩码,服务端发往客户端的帧不掩码。
  • Payload Length:载荷长度,7位、7+16位或7+64位三种表示。
  • Masking-Key:4字节掩码密钥,用于对载荷做异或运算。

行情推送通常使用文本帧承载JSON,或二进制帧承载紧凑的Protobuf/自定义结构。Ping/Pong帧用于心跳保活,是断线检测的重要手段。

三、全双工通信:真正的双向实时通道

全双工意味着客户端和服务端可以在同一连接上同时发送和接收数据,互不阻塞。这与HTTP/1.1的“半双工”形成鲜明对比:HTTP请求发出后,客户端必须等待响应,期间无法在同一连接上主动推送。WebSocket建立后,服务端可在行情变化瞬间主动推送,客户端也可随时发送订阅、撤订、查询等指令。

在行情场景中,全双工带来的典型能力包括:客户端动态调整订阅标的,服务端实时推送增量行情,双方通过心跳帧维持连接状态。这种模式显著降低了延迟和连接开销。

WebSocket 握手与全双工数据流 客户端 浏览器 / 行情终端 服务端 行情推送网关 ① HTTP Upgrade 握手请求 ② 101 Switching Protocols ③ 全双工数据帧通道(同一 TCP 连接) 订阅指令 / 心跳 Ping 行情推送 / Pong / 增量更新 帧结构:FIN | Opcode | Mask | Payload Length | Masking-Key | Payload

四、与HTTP轮询、SSE的对比

实时数据获取方案并非只有WebSocket。理解三者的差异,有助于在行情系统中做出合理选型。

对比维度 HTTP短轮询 HTTP长轮询 SSE WebSocket
通信方向 单向请求 单向请求 服务端→客户端 双向全双工
实时性 差,取决于间隔 较好 好 最好
连接开销 高,频繁建连 中,挂起等待 低,单连接 低,单连接
协议基础 HTTP HTTP HTTP HTTP升级后独立协议
行情场景适配 不推荐 低频可用 仅推送可用 推荐

SSE基于HTTP,天然支持断线重连和事件ID,适合服务端单向推送;但它不支持客户端主动发送指令,且浏览器对同一域名的SSE连接数有限制。WebSocket则同时满足双向通信和高频推送需求,是行情订阅的首选。

五、误区与复盘

误区一:WebSocket握手成功后仍然是HTTP。实际上101响应之后,协议已切换为WebSocket帧格式,不能再按HTTP解析。

误区二:客户端帧可以不掩码。RFC 6455规定客户端发往服务端的帧必须掩码,否则服务端应关闭连接。这是常见的手写客户端错误。

误区三:WebSocket自带断线重连。协议本身不提供重连机制,需要应用层实现心跳检测、指数退避重连和订阅恢复。