Python中flask-SocketIO客户端使用原生WebSocket连接失败,但使用socket.io却能正常连接的原因是什么?
Python 2.7 使用 flask_socketio(3.0.1) 时,浏览器控制台下用原生
var socket = new WebSocket("ws://127.0.0.1:5000/char")
错误信息如下:
VM167:1 WebSocket connection to 'ws://127.0.0.1:5000/chat' failed: Error during WebSocket handshake: Unexpected response code: 200
引入 socket.io 后
socket = io.connect('ws://127.0.0.1:5000/chat')
查看 socket 的 connected 属性显示为 true。
flask_socketio 的 git 地址: https://github.com/miguelgrinberg/Flask-SocketIO
是不是只能使用 socket.io 创建 client 进行连接?给的 demo 也都是使用 socket.io 。
求踩过坑的朋友指点一下,谢谢!
Python中flask-SocketIO客户端使用原生WebSocket连接失败,但使用socket.io却能正常连接的原因是什么?
socket.io 用了 polling 模式吗?
这个问题核心在于Flask-SocketIO服务器默认使用Socket.IO协议,而原生WebSocket是另一个协议。
Flask-SocketIO是基于Socket.IO库实现的,它并不是纯WebSocket服务器。Socket.IO协议在WebSocket之上添加了一层自己的封装,包括:
- 心跳机制
- 自动重连
- 命名空间和房间
- 事件驱动的消息格式
- 回退机制(当WebSocket不可用时使用轮询)
当你用原生WebSocket客户端连接时,服务器期望收到Socket.IO格式的消息(如2probe、5这样的握手包),但原生WebSocket发送的是标准WebSocket帧,协议不匹配自然连接失败。
示例对比:
# Flask-SocketIO服务器端
from flask import Flask
from flask_socketio import SocketIO
app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="*")
@socketio.on('message')
def handle_message(data):
print('received message:', data)
if __name__ == '__main__':
socketio.run(app, port=5000)
// 能连接的Socket.IO客户端
<script src="https://cdn.socket.io/4.5.0/socket.io.min.js"></script>
<script>
const socket = io('http://localhost:5000');
socket.emit('message', 'Hello Socket.IO');
</script>
// 会失败的原生WebSocket客户端
<script>
const ws = new WebSocket('ws://localhost:5000');
ws.onopen = () => {
ws.send('Hello'); // 这里发送的是纯文本,不是Socket.IO格式
};
</script>
解决方案:
- 如果要用原生WebSocket,服务器端需要用纯WebSocket库(如websockets)
- 如果要用Flask-SocketIO,客户端必须用Socket.IO客户端库
简单说:协议不同,别混着用。
你是说客户端吗?应该没有。我只是测试了下能不能连接成功。
是的,只能用 socket.io 的 client。我这边本来有个 python ws 的需求,现在就是一直往后延。。。python 做 web 可能确实不是特别合适吧。。
这就有点蛋疼了。。。 好像 tornado 没有这个问题。
F12 看下 network 里面 ws 有没有包。
client 用的是 socket.io 吗?
是
用 new 出来的 WebSocket 去连接会看到 WS 里面有包,但是用 socket.io 看不到。
好吧,我用 socket.io 也是没有问题的。
地址对了吗,flask socketio 就是那个作者写的 socketio 的 Py 版本,但是客户端应该不影响,只要是个 ws
看看是不是 python 少了一个依赖,貌似叫 gevent ?如果 websoket 建立不了链接,socket.io 会自动退化到 polling 模式。
咦,那有可能是,实现的不是单纯的 websocket 协议
socket io 服务器和客户端虽然可以通过 websocket 连接 但是不能用浏览器原生的 websocket 连接 socket io 服务器 socket io 有自己自定义的一套协议。
问一个问题:使用 socket.io 做服务端能直接用 websocket 当做客户端链接么?
这个是装了的,因为没装的时候会有 Warning。但是我用 flask_socketio 作者自己的 demo 跑,显示的链接也是 /socket.io/?EIO=3&transport=polling&t=1530787155994-0 这种
/char or /chat?
谢谢提醒,刚去我测试代码看了下,代码里没有错。帖子里写错了。
socket.io 连不着时会 fallback 到 http
&transport=polling 基本就是用了 polling 模式,基于 http 长轮询,并不是 ws
websocket 只是 socket.io 的其中一种工作方式。
flask-sockerio 是假的 websocket,建议用 tornado
flask-socketio 是真的 websocket 好吧
nginx 关于 websocket 的配置可以上网搜一搜,一堆。flask-socketio 的支持和前端使用的库有关,原生的是不支持的。你可以找个测试网站试试就知道了


