Flask SocketIO与React socket.io-client无法连接问题求助
问题描述
我花了两天时间尝试让Flask SocketIO与React的socket.io-client正常通信,试过Stack Overflow上同类问题的各种解决方案,都没有效果。浏览器控制台中socket对象的connected状态始终显示为false,恳请帮忙排查问题。
服务端依赖版本
Package Version ------------------------- ------------ aniso8601 9.0.1 APScheduler 3.10.4 attrs 23.1.0 bidict 0.22.1 blinker 1.7.0 cachelib 0.9.0 certifi 2023.11.17 cffi 1.16.0 charset-normalizer 3.3.2 click 8.1.7 colorama 0.4.6 flasgger 0.9.7.1 Flask 3.0.0 Flask-Caching 2.1.0 Flask-Cors 4.0.0 Flask-JWT-Extended 4.5.3 Flask-RESTful 0.3.10 Flask-SocketIO 5.3.6 Flask-SQLAlchemy 3.1.1 gevent 23.9.1 gevent-websocket 0.10.1 greenlet 3.0.1 h11 0.14.0 idna 3.6 itsdangerous 2.1.2 Jinja2 3.1.2 jsonschema 4.20.0 jsonschema-specifications 2023.11.2 MarkupSafe 2.1.3 mistune 3.0.2 oauthlib 3.2.2 packaging 23.2 pycparser 2.21 PyJWT 2.8.0 python-engineio 4.8.2 python-socketio 5.11.0 pytz 2023.3.post1 PyYAML 6.0.1 referencing 0.32.0 requests 2.31.0 requests-oauthlib 1.3.1 rpds-py 0.13.2 schedule 1.2.1 scheduler 0.8.5 simple-websocket 1.0.0 six 1.16.0 SQLAlchemy 2.0.23 typeguard 4.1.5 typing_extensions 4.8.0 tzdata 2023.3 tzlocal 5.2 urllib3 2.1.0 Werkzeug 3.0.1 wsproto 1.2.0 zope.event 5.0 zope.interface 6.1
服务端代码(run.py)
from app import create_app, db from threading import Lock from flask import Flask, render_template, session, request, \ copy_current_request_context from flask_socketio import SocketIO, emit, disconnect from flask_cors import CORS async_mode = None app = Flask(__name__) app.config['SECRET_KEY'] = 'secret!' CORS(app, resources={r"/*": {"origins": "*"}}) socketio = SocketIO(app, cors_allowed_origins="*") count = 0 app = create_app() @socketio.on("connect") def connected(): """event listener when client connects to the server""" print("client has connected") emit("connect", {"data": f"It is connected"}) if __name__ == '__main__': with app.app_context(): db.create_all() # app.run(port=8080, debug=True) socketio.run(app, port=8080, debug=True)
客户端依赖版本
"react": "^18.2.0", "react-apexcharts": "^1.4.1", "react-beautiful-dnd": "^13.1.1", "react-bootstrap": "^2.9.1", "react-date-range": "^1.4.0", "react-daterange-picker": "^2.0.1", "react-dom": "^18.2.0", "react-form-stepper": "^2.0.3", "react-gauge-chart": "^0.4.1", "react-helmet": "^6.1.0", "react-moment": "^1.1.3", "react-pro-sidebar": "^1.1.0-alpha.1", "react-router-dom": "^6.19.0", "react-scripts": "5.0.1", "socket.io-client": "^4.5.1", "uuid": "^9.0.1", "web-vitals": "^2.1.4"
客户端连接代码
useEffect(() => { socket = io('localhost:8080', { extraHeaders: { "X-API-KEY": 'secret', "X-APP-NAME": 'testapp' } }, { cors: { origin: "http://localhost:3000/", }, } ); console.log(socket); socket.on('connect', () => { console.log("Connected!"); }); // when connected, look for when the server emits the updated count socket.on('counter updated', function(countFromServer) { // set the new count on the client setCount(countFromServer); }) }, []);
核心问题及修复方案
服务端app实例覆盖问题
服务端代码中,你先创建了一个Flask实例并绑定了socketio,但随后执行app = create_app()覆盖了该实例,导致最终运行的app没有配置socketio。修复方式:将socketio初始化移到create_app()之后,确保绑定到正确的app实例。
修复后的run.py片段:app = create_app() # 先获取正确的app实例 app.config['SECRET_KEY'] = 'secret!' CORS(app, resources={r"/*": {"origins": "*"}}) socketio = SocketIO(app, cors_allowed_origins="*")客户端连接参数错误
调用io()时传入了多个独立的options对象,需合并为一个;同时URL建议加上http://前缀,避免解析异常。修复后的客户端代码:useEffect(() => { socket = io('http://localhost:8080', { extraHeaders: { "X-API-KEY": 'secret', "X-APP-NAME": 'testapp' }, cors: { origin: "http://localhost:3000" // 去掉末尾斜杠,匹配实际来源 } }); console.log(socket); socket.on('connect', () => { console.log("Connected!"); }); socket.on('counter updated', function(countFromServer) { setCount(countFromServer); }) }, []);事件名冲突
服务端emit的connect是socket.io内置事件名,建议改用自定义名称(如connection_ack),避免和内置事件逻辑冲突。
内容的提问来源于stack exchange,提问作者iowasandroid
相关产品推荐
相关产品推荐

