启动 websocket 服务器最简路径是三步:定义异步处理函数、调用 websockets.serve()、运行 asyncio.run_forever();关键在连接后不主动断开,需用 async for 循环持续收消息并响应。

怎么启动一个能跑通的 WebSocket 服务器?
用 websockets 库写服务端,最简路径是三步:定义处理函数、调用 websockets.serve()、运行事件循环。关键不是“能不能连上”,而是“连上后会不会断”。
常见错误现象:
- 浏览器控制台报
WebSocket connection to 'ws://localhost:8765' failed:大概率是没跑asyncio.run_forever(),协程启动了但主线程退出了 - 连上立刻断开:
handle_connection函数里漏了await websocket.recv()或没加async for循环,协程执行完就自动关闭连接
实操建议:
- 用
async for message in websocket:替代手动recv(),它会自动处理连接关闭和异常退出 - 绑定地址别写
"0.0.0.0"就直接上线,本地调试用"localhost"更安全,也避免跨域混淆 - 启动命令别手敲
python server.py就完事,加个if <strong>name</strong> == "<strong>main</strong>":保护块,防止模块导入时意外触发服务
浏览器直连为什么收不到回消息?
WebSocket 协议本身不拦跨域,但很多初学者卡在这儿,其实是服务端没做响应——不是浏览器不让连,是连上了但服务端静音。
立即学习“Python免费学习笔记(深入)”;
常见错误现象:
- 控制台显示
Connected to ws://localhost:8765,但onmessage从不触发 - 服务端日志有
Received message: xxx,但没看到await websocket.send(...)的输出
实操建议:
- 检查发送逻辑是否在
async for循环内,而不是只在连接建立时发一次(比如放在on_open类似位置,但websockets库没有这个回调) - 中文必须传字符串,不是
bytes:await websocket.send("你好")✅,await websocket.send(b"\xe4\xbd\xa0\xe5\xa5\xbd")❌,后者会触发TypeError - 浏览器测试时,别只发一次就关页面,
ws.send()后要等服务端send返回,再触发onmessage;可先用console.log("sent")确认前端发出了
多个客户端之间怎么广播消息?
websockets 默认不维护连接列表,每个 websocket 对象只代表单次连接。想群发,得自己管住所有活跃连接。
常见错误现象:
- 用
for ws in connected:+await ws.send(...),结果程序卡死或报RuntimeError: await wasn't used with a coroutine - 广播时部分客户端收不到,或收到重复消息
实操建议:
- 所有连接存进一个
set(非list),用asyncio.create_task()或asyncio.wait()并发发送,别用同步for+await - 连接断开时务必从集合中移除:
connected.remove(websocket),否则下次广播会向已关闭的 socket 写数据,抛ConnectionClosedError - 不要在处理函数里直接
try/except ConnectionClosedError后吞掉异常,得配合finally清理连接,否则内存泄漏
Python 客户端连接老是断开或收不到响应?
用 websocket-client 写脚本主动连服务端,和浏览器行为不同:它默认不维持心跳,也不自动重连,一不留神就“发完即走”。
常见错误现象:
-
ws.send()成功,但ws.recv()阻塞超时或直接抛WebSocketTimeoutException - 脚本运行完进程就退出,根本等不到服务端响应
实操建议:
- 必须显式设置
timeout参数:websocket-client的create_connection("ws://...", timeout=5) - 别依赖
on_message回调自动处理——它需要run_forever()长驻,而多数自动化场景要的是“发一条、收一条、退出”,此时该用阻塞式recv() - 如果服务端是
websockets库写的,注意它默认不发 ping/pong 帧;客户端设了keepalive=True反而可能因无响应被断开,不如关掉保持连接,靠业务层重试
复杂点在于连接生命周期管理——服务端要防假在线,客户端要懂什么时候该重连。这些逻辑不会自动出现,得一行行写进去,上线前一定用断网、杀进程、快速重连这些 case 过一遍。










