Flask-SocketIO服务器使用轮询而不是WebSockets

RPi*_*ess 4 python websocket socket.io flask-socketio

我正在Flask-SocketIO服务器上工作正常。

但是,我的服务器日志中收到很多这样的请求:

"GET /socket.io/?EIO=3&transport=polling&t=LBS1TQt HTTP/1.1"

这是我正在使用的代码:

from flask import Flask, render_template, redirect, url_for
from flask_socketio import SocketIO, emit
import json

def load_config():
    # configuration
    return json.load(open('/etc/geekdj/config.json'))

config = load_config()

geekdj = Flask(__name__)

geekdj.config["DEBUG"] = config["debug"]
geekdj.config["SECRET_KEY"] = config["secret_key"]
geekdj.config.from_envvar("FLASKR_SETTINGS", silent=True)

socketio = SocketIO(geekdj)

@geekdj.route('/')
def index():
    return render_template('index.html')

# SocketIO functions

@socketio.on('connect')
def chat_connect():
    print ('connected')

@socketio.on('disconnect')
def chat_disconnect():
    print ("Client disconnected")

@socketio.on('broadcast')
def chat_broadcast(message):
    print ("test")
    emit("chat", {'data': message['data']})

if __name__ == "__main__":
    socketio.run(geekdj, port=8000)
Run Code Online (Sandbox Code Playgroud)

和JS中的index.html

<script src="//cdn.socket.io/socket.io-1.4.5.js"></script>
<script type="text/javascript" charset="utf-8">
    $(document).ready(function(){

        // the socket.io documentation recommends sending an explicit package upon connection
        // this is specially important when using the global namespace
        var socket = io.connect('http://localhost:8000');

        socket.on('connection', function(socket) {
            socket.emit('foo', {foo: "bar"});
            socket.join("test");
        });

        socket.on('joined', function(data) {
            console.log('Joined room!');
            console.log(data["room"]);
        });
     });
Run Code Online (Sandbox Code Playgroud)

如果可能的话,我宁愿使用实际的Websocket,有人知道为什么SocketIO会回退到轮询吗?

jac*_*cob 6

第一个答案有效吗?如果是这样,您应该接受它。如果没有,请发布您的requirements.txt。

我遇到了同样的问题,并通过完全吸收文档页面找到了解决方法:

该程序包所依赖的异步服务可以在三个选择中选择:

  • eventlet是性能最好的选项,并支持长轮询和WebSocket传输。
  • 许多不同的配置都支持gevent。gevent软件包完全支持长轮询传输,
    但是与eventlet不同,gevent不具有本机WebSocket支持。
    要增加对WebSocket的支持,目前有两个选择。
    安装gevent-websocket软件包可以为
    gevent 添加WebSocket支持,或者可以使用带有
    WebSocket功能的uWSGI Web服务器。gevent的使用也是一个性能
    选项,但比eventlet略低。
  • 也可以使用基于Werkzeug的Flask开发服务器,但要注意的是,它缺乏其他两个
    选项的性能,因此只能用于简化开发
    工作流程。此选项仅支持长轮询传输。

基本上,我的虚拟环境中没有evenlet和gevent-websocket。我安装了eventlet,并且传输升级到websocket几乎是瞬时的!希望这可以帮助。

  • 您究竟是如何使用eventlet来使socketio正常工作的?您是否调用了“eventlet.monkey_patch()”或? (2认同)

RPi*_*ess 5

在其他Q / A中找到了解决方案。

事实证明SocketIO设置了具有最新连接类型的cookie。就我而言,它正在轮询。

因此,我更改了JS中的SocketIO connect语句,从

var socket = io.connect('http://localhost:8000');

var socket = io.connect(null, {port: 8000, rememberTransport: false});

现在Chrome开发者工具的“网络”标签下的websockets类型有活动(以前没有):

在此处输入图片说明