Node.js Socket.IO客户端与Python WebSocket服务器连接异常排查
问题核心原因
Socket.IO客户端和原生WebSocket服务器完全不兼容——哪怕你设置了transports: ['websocket']也没用。Socket.IO并非原生WebSocket的简单封装,它在原生协议之上额外添加了自己的握手流程、事件分发机制和命名空间规则,纯原生WebSocket服务器根本识别不了它的连接请求,这就是客户端持续重连的根本原因。
两种解决方案
你可以选择以下任意一种方案来解决问题:
方案一:Python端改用Socket.IO服务器
既然Node.js用了Socket.IO,那Python端也需要使用对应的Socket.IO库来实现服务器,推荐使用python-socketio(配合ASGI服务器如uvicorn)。
修改后的Python代码
import uvicorn import socketio # 创建ASGI兼容的Socket.IO服务器 sio = socketio.AsyncServer(cors_allowed_origins="*") app = socketio.ASGIApp(sio) @sio.event async def connect(sid, environ): # 解析请求参数 query_string = environ.get('QUERY_STRING', '') query_params = dict(qc.split('=') for qc in query_string.split('&') if qc) template_name = query_params.get('name') if template_name: # 通过Socket.IO事件发送数据 await sio.emit('templateReply', {'templateReply': 'RecivedData'}, to=sid) # 主动断开连接 await sio.disconnect(sid) if __name__ == '__main__': uvicorn.run(app, host='0.0.0.0', port=8000)
调整后的Node.js代码
const io = require('socket.io-client'); let _io = io.connect('http://localhost:8000', { transports: ['websocket'], query: { 'name': 'monk', 'POST': 'dotsinspace@gmail.com' } }); // Socket.IO的连接成功事件是'connect',不是'connection' _io.on('connect', () => { console.log('connected to server....'); }); // 监听服务器发送的自定义事件 _io.on('templateReply', (data) => { console.log('Received data:', data); }); _io.on('reconnecting', (attempt) => { console.log('Reconnecting attempt:', attempt); });
方案二:Node.js端改用原生WebSocket客户端
如果想保留Python的原生WebSocket服务器,Node.js需要使用原生WebSocket API或者ws库来连接,放弃Socket.IO。
Node.js代码(使用原生WebSocket)
const WebSocket = require('ws'); // 原生WebSocket需要把参数直接拼在URL上 const ws = new WebSocket('http://localhost:8000?name=monk&POST=dotsinspace@gmail.com'); ws.on('open', () => { console.log('Connected to server'); }); ws.on('message', (data) => { const message = JSON.parse(data); console.log('Received data:', message); }); ws.on('close', () => { console.log('Connection closed'); }); ws.on('error', (error) => { console.error('WebSocket error:', error); });
修正后的Python代码
同时要修复原Python代码中的几个小问题:
import asyncio from starlette.applications import Starlette from starlette.websockets import WebSocket import uvicorn App = Starlette() App.debug = True _port = 8000 _host = '0.0.0.0' # 配置WebSocket路由(如果Node.js用了/chat路径,这里改成/chat即可) @app.websocket_route('/') async def websocket_endpoint(websocket): await websocket.accept() _templateName = websocket.query_params.get('name') if _templateName: # 移除多余的mode参数,Starlette默认会用二进制模式发送JSON await websocket.send_json({'templateReply': 'RecivedData'}) await websocket.close() if __name__ == '__main__': uvicorn.run(App, host=_host, port=_port)
内容的提问来源于stack exchange,提问作者Manu Yadav
相关产品推荐
相关产品推荐

