mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
396 字
1 分钟
WebSocket 协议:双向通信
2023-09-09

前言#

HTTP 是请求-响应模型,WebSocket 实现了真正的双向通信。本章详解 WebSocket 协议、帧格式、代理穿透与 Socket.IO。

相关章节

一、WebSocket 协议概述#

1.1 与 HTTP 对比#

特性HTTPWebSocket
连接方向客户端发起请求双向隧道
通信方式请求-响应全双工
实时性轮询/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.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXVoZSBwbGVhc0ZyYWllbA==
Sec-WebSocket-Version: 13

2.2 服务端响应#

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-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类型说明
0x0Continuation分片消息的后续帧
0x1Text文本数据 (UTF-8)
0x2Binary二进制数据
0x8Close关闭连接
0x9Ping心跳检测
0xAPong心跳响应

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):
pass

4.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/
作者
Souloss
发布于
2023-09-09
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时