WebSocket 基础
约 1274 字大约 4 分钟
2026-05-10
阅读导览
WebSocket 基础
WebSocket 是一种支持客户端和服务端双向实时通信的协议。HTTP 通常是请求—响应模型,而 WebSocket 建立连接后,双方都可以主动发送消息。
- 适用场景
- 与 HTTP 的区别
- websockets 库
- 服务端
实践清单
学习练习清单
- 1实时双向选 WebSocket,普通增删改查继续用 HTTP —— 别把 WebSocket 当万能。
- 2用 websockets 库(pip install websockets):服务端 websockets.serve + handler,客户端 websockets.connect。
- 3消息体永远走 JSON:{'type': 'chat', ...} 这种带 type 字段的格式便于以后扩展。
- 4长连接必须做:心跳(ping/pong)、断线重连、鉴权(首条消息或子协议)、消息去重。
- 5服务端要限制单消息大小(防止 OOM),并处理客户端异常断开 —— 长连接资源不是免费的。
WebSocket 是一种支持客户端和服务端双向实时通信的协议。HTTP 通常是请求—响应模型,而 WebSocket 建立连接后,双方都可以主动发送消息。
适用场景
WebSocket 适合:
- 聊天室
- 实时通知
- 实时日志
- 在线协作
- 实时行情
- 游戏状态同步
与 HTTP 的区别
| 对比 | HTTP | WebSocket |
|---|---|---|
| 通信模式 | 请求—响应 | 双向通信 |
| 连接 | 通常短连接或连接池 | 长连接 |
| 服务端主动推送 | 不自然 | 天然支持 |
| 适合场景 | API、网页、文件 | 实时消息 |
websockets 库
安装:
pip install websockets服务端
import asyncio
import websockets
async def handler(websocket):
async for message in websocket:
await websocket.send(f'echo: {message}')
async def main():
async with websockets.serve(handler, 'localhost', 8765):
await asyncio.Future()
asyncio.run(main())客户端
import asyncio
import websockets
async def main():
async with websockets.connect('ws://localhost:8765') as websocket:
await websocket.send('hello')
message = await websocket.recv()
print(message)
asyncio.run(main())消息格式
WebSocket 只负责传输消息,业务格式通常使用 JSON。
import json
await websocket.send(json.dumps({'type': 'chat', 'text': 'hello'}))心跳和重连
长连接必须考虑:
- 心跳检测
- 断线重连
- 超时关闭
- 连接认证
- 消息顺序
- 重复消息处理
注意事项
- WebSocket 是长连接,会占用服务端资源。
- 不要无限制接收大消息。
- 需要鉴权,不能任何人都能连接。
- 客户端要实现断线重连。
- 服务端要处理异常断开。
HTTP 轮询和 WebSocket 的区别
如果页面需要实时更新,最笨的方法是轮询:
客户端:有新消息吗?
服务端:没有。
客户端:有新消息吗?
服务端:没有。
客户端:有新消息吗?
服务端:有,这里是消息。轮询简单,但请求很多,实时性也一般。
WebSocket 更像是双方先建立一条长连接:
客户端:我们保持连接吧。
服务端:可以。
服务端:有新消息时我直接推给你。所以 WebSocket 常用于聊天、协作编辑、实时通知、行情推送、游戏状态同步等场景。
一个最小聊天式示例
服务端:
import asyncio
import websockets
async def echo(websocket):
async for message in websocket:
print('收到:', message)
await websocket.send(f'服务端已收到:{message}')
async def main():
async with websockets.serve(echo, '127.0.0.1', 8765):
print('WebSocket 服务已启动')
await asyncio.Future()
asyncio.run(main())客户端:
import asyncio
import websockets
async def main():
async with websockets.connect('ws://127.0.0.1:8765') as websocket:
await websocket.send('你好')
reply = await websocket.recv()
print(reply)
asyncio.run(main())运行时同样建议开两个终端:先启动服务端,再运行客户端。
消息格式建议用 JSON
WebSocket 只负责传消息,不规定你的业务消息长什么样。为了方便扩展,常见做法是传 JSON 字符串:
import json
message = {
'type': 'chat',
'content': '你好',
}
await websocket.send(json.dumps(message, ensure_ascii=False))接收方解析:
raw = await websocket.recv()
data = json.loads(raw)
if data['type'] == 'chat':
print(data['content'])这样以后要增加 type='ping'、type='notification' 之类的消息,也更容易维护。
断线重连要怎么想
真实网络环境里,WebSocket 连接可能会断开:电脑休眠、网络切换、服务器重启、代理超时都可能导致断线。
客户端通常需要:
- 发现连接断开;
- 等一小段时间;
- 重新连接;
- 必要时重新登录或补拉消息。
初学阶段不用马上写很复杂的重连系统,但要知道:WebSocket 不是“连上后永远不断”。
WebSocket 不适合什么
WebSocket 适合实时双向通信,但不是所有请求都该用它。
| 场景 | 更合适的方式 |
|---|---|
| 获取文章列表 | HTTP GET |
| 提交表单 | HTTP POST |
| 上传文件 | HTTP / 对象存储 |
| 实时聊天 | WebSocket |
| 服务端推送通知 | WebSocket / SSE |
普通增删改查接口继续用 HTTP,会更简单、更容易调试和缓存。
总结
WebSocket 适合实时双向通信。它不是 HTTP API 的替代品,而是实时消息场景的补充。
重点总结
要点回收
- WebSocket 适合实时双向通信,普通查询和提交仍然优先用 HTTP。
- 学习时用两个终端分别运行服务端和客户端,更容易理解连接过程。
- 真实 WebSocket 程序要考虑消息格式、心跳、断线重连和鉴权。
版权所有
版权归属:Shuo Liu
