You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:05:44