Flask-SocketIO通过sid推送消息客户端无法接收问题
Flask-SocketIO 按sid推送消息客户端无法接收问题修复
问题现象
客户端可正常连接服务端,服务端也能成功获取到客户端对应的sid,但尝试通过sid向客户端推送消息时,客户端无法接收到任何来自服务端的消息。
本人英语水平有限,敬请谅解。
原有问题代码
服务端 server.py
app = Flask(__name__) app.config['SECRET_KEY'] = 'secret!' socketio = SocketIO(app) tokenList = {} @app.route("/test") def testConnect(): sid = tokenList["114514"] print(sid) emit('newMission', {'from': 'server'}, namespace="newMission", to=sid) return 'success' @socketio.on('register') def register(data): print("服务器%s尝试注册" % data["secret"]) emit('register', {"token": "1919810"}) print("注册成功,token为%s" % "1919810") sid = request.sid join_room("mainRoom") tokenList["114514"] = sid """@socketio.on('message') def message(data): print(data) # {'from': 'client'} emit('response', {'from': 'server'}) sleep(5) emit('response', "exit")""" if __name__ == '__main__': socketio.run(app, debug=True, host='127.0.0.1', port=8090)
客户端 client.py
import socketio sio = socketio.Client() @sio.event() def connect(): print('正在注册,请稍后') sio.emit('register', {'secret': '114514'}) @sio.on('register') def isReg(data): print("注册成功,当前token为" + data["token"]) @sio.on("newMission", namespace="message") def newMission(data): print(data) sio.connect('ws://localhost:8090') sio.wait()
问题根因
- 核心错误是命名空间不匹配:服务端发送
newMission事件时指定命名空间为newMission,客户端监听该事件时绑定的命名空间为message,且客户端从未连接过这两个自定义命名空间,所有连接、事件交互默认都在根命名空间/下,消息根本无法路由到客户端的监听函数。 - 普通HTTP路由(
/test接口)不属于SocketIO事件上下文,直接调用事件上下文专属的emit()方法会出现上下文缺失问题,无法正确推送消息。
修复方案
- 无特殊多命名空间需求时,全部使用默认根命名空间,删除所有事件发送、监听处错误的自定义namespace参数;如果必须使用自定义命名空间,需保证客户端连接、事件监听、服务端事件发送三处的命名空间字符串完全一致。
- 在普通HTTP路由中推送SocketIO消息时,使用初始化得到的
socketio实例的emit方法,不要直接使用上下文中的emit。
修复后服务端代码
from flask import Flask, request from flask_socketio import SocketIO, emit, join_room app = Flask(__name__) app.config['SECRET_KEY'] = 'secret!' socketio = SocketIO(app) tokenList = {} @app.route("/test") def testConnect(): sid = tokenList["114514"] print(sid) # 普通路由调用socketio实例的emit方法,移除错误的namespace参数 socketio.emit('newMission', {'from': 'server'}, to=sid) return 'success' @socketio.on('register') def register(data): print("客户端%s尝试注册" % data["secret"]) emit('register', {"token": "1919810"}) print("注册成功,token为%s" % "1919810") sid = request.sid join_room("mainRoom") tokenList["114514"] = sid if __name__ == '__main__': socketio.run(app, debug=True, host='127.0.0.1', port=8090)
修复后客户端代码
import socketio sio = socketio.Client() @sio.event() def connect(): print('正在注册,请稍后') sio.emit('register', {'secret': '114514'}) @sio.on('register') def isReg(data): print("注册成功,当前token为" + data["token"]) # 移除错误的namespace参数,和服务端发送事件的命名空间保持一致 @sio.on("newMission") def newMission(data): print("收到服务端推送:", data) sio.connect('ws://localhost:8090') sio.wait()
修复后启动服务,访问http://127.0.0.1:8090/test,客户端即可正常收到推送的newMission事件消息。
内容的提问来源于stack exchange,提问作者IcyCoffee4513
相关产品推荐
相关产品推荐

