396 字
1 分钟
WebSocket 协议:双向通信
前言
HTTP 是请求-响应模型,WebSocket 实现了真正的双向通信。本章详解 WebSocket 协议、帧格式、代理穿透与 Socket.IO。
相关章节:
- TLS 与 HTTPS 协议 — WSS 安全连接依赖 TLS
- OAuth2 与 OIDC 协议 — WebSocket 认证机制
- HTTP/2:多路复用 — HTTP/2 与 WebSocket 的对比
一、WebSocket 协议概述
1.1 与 HTTP 对比
| 特性 | HTTP | WebSocket |
|---|---|---|
| 连接方向 | 客户端发起请求 | 双向隧道 |
| 通信方式 | 请求-响应 | 全双工 |
| 实时性 | 轮询/SSE | 真正推送 |
| 断线重连 | 手动处理 | 自动重连 |
1.2 协议升级流程
sequenceDiagram
participant C as Client
participant S as Server
Note over C,S: HTTP 握手阶段
C->>S: GET /ws HTTP/1.1<br/>Upgrade: websocket<br/>Sec-WebSocket-Key: xxx
S->>C: HTTP/1.1 101 Switching Protocols<br/>Sec-WebSocket-Accept: yyy
Note over C,S: WebSocket 连接建立
C->>S: Frame (Text/Binary)
S->>C: Frame (Text/Binary)
C->>S: Ping
S->>C: Pong
Note over C,S: 双向通信中...
C->>S: Close Frame
S->>C: Close Frame
Note over C,S: 连接关闭
1.3 连接状态机
stateDiagram-v2
[*] --> CONNECTING: new WebSocket()
CONNECTING --> OPEN: 握手成功 (101)
CONNECTING --> CLOSED: 握手失败
OPEN --> CLOSING: close() 或收到 Close Frame
OPEN --> CLOSED: 连接异常断开
CLOSING --> CLOSED: Close 握手完成
CLOSED --> [*]
note right of OPEN
可发送/接收数据
心跳检测活跃
end note
二、握手协议
2.1 客户端握手请求
GET /ws HTTP/1.1Host: example.comUpgrade: websocketConnection: UpgradeSec-WebSocket-Key: dGhlIHNhbXVoZSBwbGVhc0ZyYWllbA==Sec-WebSocket-Version: 132.2 服务端响应
HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: s3pCLPLi0ixlEOVwpN3koWSygYs=三、帧格式
3.1 WebSocket 帧结构
block-beta
columns 8
block:header1:2
FIN["FIN<br/>1bit"]
RSV["RSV1-3<br/>3bits"]
end
block:header2:2
OPC["Opcode<br/>4bits"]
MASK["Mask<br/>1bit"]
end
block:header3:2
LEN["Payload Len<br/>7bits"]
ELEN["Extended Len<br/>0/2/8 bytes"]
end
block:payload:2
KEY["Masking Key<br/>4 bytes"]
DATA["Payload Data<br/>N bytes"]
end
3.2 Opcode 类型
| Opcode | 类型 | 说明 |
|---|---|---|
| 0x0 | Continuation | 分片消息的后续帧 |
| 0x1 | Text | 文本数据 (UTF-8) |
| 0x2 | Binary | 二进制数据 |
| 0x8 | Close | 关闭连接 |
| 0x9 | Ping | 心跳检测 |
| 0xA | Pong | 心跳响应 |
3.3 帧解析示例
# RSV1/RSV2/RSV3: 保留位 (用于扩展)# OPCODE: 0x1=文本帧 0x2=二进制帧 0x8=关闭帧frame = { "fin": True, # 完整消息 "opcode": 0x1, "masked": True, "masking_key": "随机4字节", "payload": "数据负载"}3.4 掩码算法
def unmask(payload: bytes, masking_key: bytes) -> bytes: """客户端发送的数据必须掩码,服务端发送的数据不掩码""" result = bytearray() for i, byte in enumerate(payload): result.append(byte ^ masking_key[i % 4]) return bytes(result)四、心跳与重连
4.1 心跳机制
import asyncio
class Heartbeat: async def ping(self): while True: await asyncio.sleep(30) await self.send_frame(opcode=0x9) # Ping
async def pong_handler(self, frame): pass4.2 自动重连
class ReconnectingWebSocket: def on_close(self): # 指数退避重连 await asyncio.sleep(min(2**attempt, 60)五、代理穿透
5.1 WebSocket 代理问题
| 代理类型 | WebSocket 问题 |
|---|---|
| HTTP 代理 | 需要 CONNECT 建立隧道 |
| 负载均衡 | 粘性会话需求 |
| NAT 穿透 | STUN/TURN 支持 |
5.2 WSS 加密
# 生产环境必须使用 WSS# wss://your-server.com/ws六、Socket.IO
6.1 架构
| 特性 | Socket.IO |
|---|---|
| 回落机制 | HTTP 长轮询 |
| 自动重连 | |
| 房间/广播 | |
| 命名空间 |
6.2 事件编程
# Socket.IO 事件@socketio.on('message')def handle_message(data): emit('response', {'response': data})
@socketio.on('connect')def connect(): emit('connected', {'session': request.sid})七、总结
WebSocket 是实时通信的核心协议,WSS + 心跳 + 重连是生产必备。
参考资料
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
WebSocket 协议:双向通信
https://blog.souloss.com/posts/web/websocket-protocol/ 部分信息可能已经过时
相关文章 智能推荐
1
TLS 与 HTTPS 协议:加密传输
网络 深度解读 TLS/SSL 握手、加密传输、HSTS 与证书固定
2
HTTP/1.0:扩展协议
web 在 HTTP/0.9 的基础上,探索 HTTP/1.0 引入的核心新特性——请求头与响应头、状态码、多种 HTTP 方法(GET/POST/HEAD),并动手实现一个支持 HTTP/1.0 的 Python 服务器。
3
HTTP/2:多路复用
web 探索 HTTP/2 如何突破 HTTP/1.1 的性能瓶颈——从 SPDY 的设计理念到二进制分帧层、多路复用、头部压缩(HPACK)、服务器推送与流优先级,用实验直观理解这些革命性改进。
4
HTTP/1.1:持久连接
web 在 HTTP/1.0 的基础上,深入探索 HTTP/1.1 的核心改进——持久连接、分块传输编码、请求管道化、内容协商、缓存增强,以及 Host 头的重要性。通过 Python 实验服务器亲手体验这些特性带来的性能提升。
5
WebRTC:实时通信协议详解
网络 深入解析 WebRTC 协议的架构、工作原理和应用场景






