python socket.io服务端防断连需用async_mode='asgi'配uvicorn,显式设cors_allowed_origins,校验路径/命名空间/房间广播参数,并确保nginx透传websocket头。

Python Socket.IO 服务端怎么写才不会断连
用 python-socketio 搭实时聊天室,最常卡在服务端一跑就掉连接——不是客户端收不到消息,就是 connect 后几秒自动 disconnect。根本原因往往是没配对异步模式,或者用了不兼容的 ASGI/WSGI 服务器。
实操建议:
- 必须确认你用的是
async_mode='asgi'(推荐)或'eventlet'/'gevent';纯threading模式在高并发下会丢包、假死 - 别用
flask.run()启动,它只支持 WSGI,而python-socketio的 WebSocket 升级需要 ASGI 支持;改用uvicorn或eventlet的serve() -
sio = socketio.Server(async_mode='asgi')和app = socketio.WSGIApp(sio)是经典组合;如果用 FastAPI,则直接挂载SocketIO实例到app.mount() - 检查客户端是否发了
ping_timeout超时(默认 60s),服务端没及时回 ping 就会被踢;可在初始化时加ping_timeout=120, ping_interval=25
客户端 connect 失败但没报错,怎么查
浏览器控制台看不到明显错误,Network 里 WebSocket 连接状态是 canceled 或 pending,大概率是跨域或路径没对上。
实操建议:
- 服务端必须显式允许跨域:初始化
sio = socketio.Server(cors_allowed_origins="*")(开发用),生产环境请写死域名如["https://yourapp.com"] - 客户端 new
io("http://localhost:8000")默认走/socket.io/路径;如果你的服务端挂载在子路径(比如app.mount("/chat", app=socket_app)),客户端就得写io("http://localhost:8000/chat") - 检查是否启用了 HTTPS 但服务端是 HTTP——浏览器会静默拒绝混合内容;本地开发可用
http://,但别在https://页面里连ws:// - 用 curl 测试握手是否通:
curl "http://localhost:8000/socket.io/?EIO=4&transport=polling",正常应返回包含"sid"的 JSON;返回 404 就说明路径或挂载点错了
发消息后只有自己收到,其他人收不到
这是最典型的命名空间(namespace)和房间(room)误用问题。默认所有事件都在 / 命名空间广播,但如果你手动进了某个 room 却没指定 skip_sid 或广播范围,消息就只发给自己。
实操建议:
- 确认是否用了
sio.enter_room(sid, room)却忘了在@sio.on('message')里用sio.emit('message', data, room=room)——漏掉room=...就只会发给当前连接(sid) - 想全局广播(除自己外):用
sio.emit('msg', data, skip_sid=sid);想全量广播(含自己):直接sio.emit('msg', data) - 命名空间不匹配会导致事件根本进不了 handler:客户端连
io("/chat"),服务端就必须写@sio.on('connect', namespace='/chat'),否则事件被忽略且无提示 - 注意
sio.send()是简写,只发给当前 sid;要广播必须用sio.emit()
为什么用 eventlet 启动后日志不输出、调试变困难
eventlet 会 monkey patch 标准库的 I/O 操作,导致部分 logging handler(尤其是带文件轮转的)阻塞或失效,print 也经常延迟甚至消失。
实操建议:
- 启动前加
import eventlet; eventlet.monkey_patch(),但紧跟着加logging.basicConfig(level=logging.INFO),避免被 patch 影响 - 别用
RotatingFileHandler,改用TimedRotatingFileHandler或直接 stdout + systemd 日志接管 - 调试时临时换回
async_mode='threading'(仅限单连接测试),能立刻看到 print 和异常堆栈 - 真正上线别用
eventlet,优先选async_mode='asgi'+uvicorn,日志、debug、中间件都更可控
真实部署时最容易被忽略的是:WebSocket 路径和反向代理配置必须完全对齐。Nginx 要透传 Upgrade 头、设置 proxy_http_version 1.1、转发 /socket.io/ 到后端,少一个环节,前端就永远在 pending 状态。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











