Day 085 — WebSocket 通信 图解
1. WebSocket 协议握手流程
┌─────────┐ ┌─────────┐
│ 客户端 │ │ 服务器 │
│ Browser │ │ Server │
└────┬────┘ └────┬────┘
│ │
│ ① HTTP Upgrade 请求 │
│ GET /chat HTTP/1.1 │
│ Host: example.com │
│ Upgrade: websocket │
│ Connection: Upgrade │
│ Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== │
│───────────────────────────────────────────────▶│
│ │
│ ② 服务器确认切换协议 │
│ HTTP/1.1 101 Switching Protocols │
│ Upgrade: websocket │
│ Connection: Upgrade │
│ Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzh... │
│◀───────────────────────────────────────────────│
│ │
│ ③ WebSocket 连接建立 │
│◄═══════════════════════════════════════════════▶│
│ │
│ ④ 双向数据传输 │
│◄═══════════════════════════════════════════════▶│
│ │
│ ⑤ 关闭连接 │
│◄───────────────────────────────────────────────│
│ │
2. HTTP 轮询 vs WebSocket 对比
HTTP 轮询(低效):
─────────────────────────────────────────────
时间轴 ─────────────────────────────────────▶
客户端: ──请求── ──请求── ──请求── ──请求──
│ │ │ │
服务器: ──响应── ──响应── ──响应── ──响应──
↑ 新数据在这里产生,但客户端不知道
WebSocket(高效):
─────────────────────────────────────────────
时间轴 ─────────────────────────────────────▶
客户端: ═══握手═════════════════════════════════
│
服务器: ════════════════════════════════════════
↑ ↑ ↑
推送数据 推送数据 推送数据
(服务器主动发送,无需客户端请求)
3. 聊天室系统架构
┌──────────────────────────────────────────────────────────┐
│ 聊天室系统架构 │
├──────────────────────────────────────────────────────────┤
│ │
│ ┌────────┐ WebSocket ┌──────────────────┐ │
│ │Alice │◄══════════════════▶│ │ │
│ └────────┘ │ │ │
│ ┌────────┐ WebSocket │ 聊天室服务器 │ │
│ │ Bob │◄══════════════════▶│ │ │
│ └────────┘ │ ┌────────────┐ │ │
│ ┌────────┐ WebSocket │ │ 连接管理器 │ │ │
│ │Carol │◄══════════════════▶│ └────────────┘ │ │
│ └────────┘ │ ┌────────────┐ │ │
│ ┌────────┐ WebSocket │ │ 消息广播器 │ │ │
│ │ Dave │◄══════════════════▶│ └────────────┘ │ │
│ └────────┘ │ ┌────────────┐ │ │
│ │ │ 心跳检测器 │ │ │
│ │ └────────────┘ │ │
│ │ ┌────────────┐ │ │
│ │ │ 消息历史 │ │ │
│ │ └────────────┘ │ │
│ └──────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ 消息日志 / 存储 │ │
│ └──────────────────┘ │
│ │
└──────────────────────────────────────────────────────────┘
4. 消息流转过程
Alice 发送消息 "你好" 给 Bob:
Alice 的客户端 聊天室服务器 Bob 的客户端
│ │ │
│── {"type":"chat", │ │
│ "content":"你好"}│ │
│────────────────────▶│ │
│ │ │
│ │── {"type":"chat", │
│ │ "username":"Alice",│
│ │ "content":"你好"} │
│ │────────────────────▶│
│ │ │
│ │ │ 显示消息
│ │ │ "[Alice] 你好"
│ │ │
│ │ (同时广播给其他用户) │
│ │ Carol, Dave... │
5. 心跳检测时序
服务端 客户端
│ │
│──── ping (每20秒) ───────────────▶│
│◀─── pong ────────────────────────│ ← 正常响应
│ │
│──── ping ────────────────────────▶│
│ │
│◀─── pong ────────────────────────│
│ │
│ │ ...连接静默断开...
│──── ping ────────────────────────▶│ ← 10秒超时
│ (等待 pong...) │
│ (超过 ping_timeout=10s) │
│ │
│ 判定连接死亡,主动关闭 │
│ 清理资源 │
│ │
6. 断线重连策略(指数退避)
重连延迟 (秒)
│
30 │ ┌─────
│ │
│ ┌─────────┘
15 │ │
│ ┌─────────┘
8 │ │
│ ┌───────┘
4 │ │
│──┘
2 │
1 │──┐
│ │
0 ├──┼──┼────┼────────┼──────────┼────▶ 重连次数
0 1 2 3 4 5
策略:每次重连延迟翻倍,最大不超过 30 秒
连接成功后延迟重置为 1 秒