目录
1、概念
WebSocket是一种革命性的网络通信协议,旨在解决传统 HTTP 协议在实现实时、双向、全双工通信方面的局限性。
HTTP的痛点:
单向性: 传统 HTTP 是请求-响应模型。客户端(如浏览器)必须主动发起请求,服务器才能响应。服务器无法主动向客户端推送数据。
无状态性: 每次请求/响应都是独立的,服务器不保留之前请求的上下文(除非使用 Cookie/Session 等机制模拟状态)。
高开销: 每个 HTTP 请求/响应都包含完整的头部信息(Header),即使数据体很小,头部开销也相对较大。对于需要频繁交换小数据包的实时应用(如聊天、游戏),这种开销不可忽视。
延迟: 为了实现“伪实时”(如轮询、长轮询、SSE),客户端需要不断发起请求或保持连接等待,这增加了延迟和服务器负担。
WebSocket的解决方案:
全双工、双向通信: 一旦建立连接,服务器和客户端可以随时、独立地相互发送数据,无需等待对方的请求。这就像在两者之间建立了一条畅通无阻的双向数据管道。
持久连接: 连接建立后,会一直保持打开状态,直到显式关闭。避免了重复建立 TCP 连接的开销(TCP 握手通常需要 1.5 RTT-往返延时)。
低开销: 建立连接后,数据传输的帧(Frame)头部非常小(最小只有 2 字节),特别适合传输小数据量和频繁交互的场景。
低延迟: 由于连接是持久的且双向的,数据可以近乎实时地传递,没有 HTTP 轮询的等待时间。
2、WebSocket工作原理
2.1 握手(Handshake - 基于 HTTP)
整个过程始于一个特殊的 HTTP 请求(通常由客户端发起)。
这个请求包含一个关键的 Header:
Upgrade: websocket
,表示客户端希望将连接升级到 WebSocket 协议。另一个关键 Header 是
Sec-WebSocket-Key
,包含一个随机的 Base64 编码值。服务器如果支持 WebSocket,会响应一个 HTTP 101 Switching Protocols 状态码。
服务器的响应包含
Sec-WebSocket-Accept
Header,其值是使用客户端发送的Sec-WebSocket-Key
和一个固定的 GUID 经过特定算法(SHA-1 + Base64)计算得出的。这个步骤至关重要,用于验证服务器确实理解 WebSocket 协议,防止恶意脚本或代理错误地建立连接。
握手成功后,底层的 TCP/IP 连接保持不变,但协议从 HTTP 升级为 WebSocket。
2.2 数据传输(Data Framing)
握手成功后,通信切换到 WebSocket 协议。
数据以帧(Frame) 为单位传输。帧有不同的类型:
文本帧: 携带 UTF-8 编码的文本数据。
二进制帧: 携带任意二进制数据(图片、音频、视频、Protobuf 等)。
控制帧: 包括连接关闭 (
Close
)、心跳检测 (Ping/Pong
) 等管理性帧。
帧结构精简: 一个基本的 WebSocket 帧包含:
FIN
(1 bit): 指示是否是消息的最后一帧(消息可以分片在多帧中传输)。RSV1, RSV2, RSV3
(各 1 bit): 保留位,用于扩展。Opcode
(4 bits): 标识帧类型(文本、二进制、关闭、Ping、Pong 等)。Mask
(1 bit): 指示负载数据是否被掩码(masked)。客户端发送给服务器的帧必须掩码,服务器发送给客户端的帧不能掩码。 这是另一个安全措施。Payload length
(7/7+16/7+64 bits): 指示负载数据的长度(可变长度编码)。Masking-key
(0 或 4 bytes): 如果Mask
位为 1,则存在 4 字节的掩码密钥。Payload data
(长度由Payload length
指定): 实际传输的数据。如果Mask
为 1,需要与Masking-key
进行异或运算以还原真实数据。
Ping/Pong 机制: 用于保持连接活跃(心跳检测)和验证对端是否仍然在线。服务器可以发送一个
Ping
帧,客户端必须用Pong
帧回应(通常自动处理)。反之亦可。
2.3 关闭连接(Closing)
任何一方(客户端或服务器)都可以发起关闭。
发送一个
Close
控制帧(包含可选的关闭状态码和原因)。接收方收到
Close
帧后,如果之前没发送过Close
帧,也应该发送一个Close
帧作为回应。双方都发送并接收到
Close
帧后,底层 TCP 连接才真正关闭。
3、关键特性和优势
真正的实时性: 极低的通信延迟,服务器消息可以瞬间推送到客户端。
双向通信: 服务器主动推送能力是核心价值。
高效:
一次握手,持久连接,省去重复的 TCP 握手和 HTTP 头开销。
数据传输帧头部极小。
减少带宽消耗: 尤其适用于高频次、小数据量的交互。
减少服务器负载: 相比 HTTP 轮询/长轮询,服务器处理连接的开销显著降低。
支持二进制和文本数据: 应用场景广泛。
基于 TCP: 提供可靠、有序的数据传输(与 UDP 不同)。
与 HTTP 协作: 使用标准端口(80-WS / 443-WSS),易于通过防火墙和代理(虽然某些配置严格的代理可能仍有问题)。
4、主要应用场景
实时聊天应用: 消息的即时发送和接收。
在线协作工具: 文档、白板的实时同步编辑。
多人在线游戏: 玩家位置、动作、状态的实时同步。
金融交易平台: 股票行情、交易订单的实时推送。
体育直播更新: 比分、赛况的即时推送。
物联网: 设备状态的实时监控和控制。
社交媒体的实时通知: 点赞、评论、新粉丝提醒。
带有实时功能的仪表盘: 监控数据(服务器性能、用户行为)的实时可视化。
5、服务器端实现
几乎所有主流后端语言和框架都有成熟的 WebSocket 库/模块:
Node.js:
ws
,Socket.IO
(封装了 WebSocket 并提供了更多功能如房间、广播、自动重连、降级方案),uWebSockets.js
(高性能)Java:
Java API for WebSocket
,Spring WebSocket
,Netty
Python:
websockets
,Django Channels
,Socket.IO
(Python 版)Go:
gorilla/websocket
.NET (C#):
System.Net.WebSockets
,SignalR
(类似 Socket.IO 的抽象层)