WebSocket 如何实现全双工通信
要理解 WebSocket 如何通过 HTTP 升级实现 全双工通信,得先明白 HTTP 的先天限制,再看它是怎么完成协议切换的。简单来说,WebSocket 是借用了 HTTP 的握手流程,一旦连接建立,就彻底脱离了 HTTP 的请求 - 响应模型。
HTTP 为什么不支持全双工?
HTTP(1.1/2)的核心设计决定了它无法原生支持全双工。它的通信模型是典型的请求 - 响应:客户端发起请求,服务端被动响应,响应完成后连接通常关闭或复用但仍以'请求 - 响应'为单位。这意味着同一时刻,同一连接上只能由一端发送数据,服务端无法主动向客户端推送。每次请求还得携带大量头部信息,且没有帧化设计,效率不高。
而全双工的定义很明确:通信双方在同一连接上,可同时向对方发送数据。就像打电话,双方可以同时说话。WebSocket 的本质就是'解锁'TCP 的全双工能力。
从 HTTP 到 WebSocket 的升级流程
WebSocket 并没有修改 HTTP 本身,而是利用 HTTP 1.1 的 Upgrade 机制作为'敲门砖'。这个过程分三步走,但逻辑上是连贯的。
1. 客户端发起升级请求
客户端向服务端发送一个特殊的 HTTP 请求,核心在于几个关键头信息:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
这里 Upgrade: websocket 和 Connection: Upgrade 是关键标识,告诉服务器我想把协议换成 WebSocket。Sec-WebSocket-Key 是一个随机生成的 base64 码,用于防伪造。
2. 服务端确认升级
服务端收到请求后,会验证密钥。它用 Sec-WebSocket-Key 加上固定魔法字符串 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 做 SHA-1 哈希并 Base64 编码,然后返回 HTTP 101 响应:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
如果浏览器用同样的算法算出的字符串和服务端传回来的不一致,连接就会断开。这一步确保了握手的安全性。
3. 协议切换完成
验证通过后,底层的 TCP 连接并没有断开,但上层协议已经从 HTTP 完全切换为 WebSocket。这是实现全双工的关键一步:TCP 本身是全双工的,HTTP 因为上层规则限制了双向通信,而 WebSocket 移除了这些限制。
WebSocket 实现全双工的核心设计
升级完成后,WebSocket 通过以下设计充分利用了 TCP 的特性。
底层依赖:TCP 的全双工特性
TCP 连接本身就是全双工字节流。每个连接有两个独立的通道(客户端→服务端、服务端→客户端),两端可同时写入数据,操作系统负责处理有序传输、重传和流量控制。HTTP 的问题在于上层协议规则浪费了 TCP 的能力,而 WebSocket 完全适配 TCP,不再限制数据传输的方向和时机。
帧化设计:打破边界
WebSocket 将数据拆分为帧(Frame),而不是 HTTP 的报文。帧是最小传输单元,特点很明显:
- 双向帧传输:客户端和服务端可随时发送帧(文本、二进制、控制等),不用等对方请求。
- 类型区分:数据帧传业务数据,控制帧(PING/PONG/CLOSE)管理连接。
- 轻量级:帧头仅 2~10 字节,远小于 HTTP 头部,且掩码仅客户端需添加,提升效率。
实际运行时,客户端和服务端可以同时发帧,TCP 栈会在两个方向分别传输,互不干扰。


