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

Flask-SocketIO server using polling instead of websockets

我正在开发一个工作正常的 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)

index.html 中的 JS:

<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"]);
        });
     });

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

我找到了解决方案 in this other Q/A

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

所以,我更改了 JS 中的 SocketIO 连接语句

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

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

现在 Chrome 开发人员工具(以前没有)的网络选项卡下的 websockets 类型中有 activity:

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

我遇到了同样的问题,通过充分吸收文档页面找到了解决方案:

The asynchronous services that this package relies on can be selected among three choices:

  • eventlet is the best performant option, with support for long-polling and WebSocket transports.
  • gevent is supported in a number of different configurations. The long-polling transport is fully supported with the gevent package,
    but unlike eventlet, gevent does not have native WebSocket support.
    To add support for WebSocket there are currently two options.
    Installing the gevent-websocket package adds WebSocket support to
    gevent or one can use the uWSGI web server, which comes with
    WebSocket functionality. The use of gevent is also a performant
    option, but slightly lower than eventlet.
  • The Flask development server based on Werkzeug can be used as well, with the caveat that it lacks the performance of the other two
    options, so it should only be used to simplify the development
    workflow. This option only supports the long-polling transport.

基本上,我的虚拟环境中既没有 evenlet,也没有 gevent-websocket。我安装了 eventlet,传输升级到 websocket 几乎是瞬间完成的!希望这有帮助。