当异步模式为“线程”时,Flask.SocketIO 无法向注册参与者异步发送数据

Mid*_*ava 2 javascript python flask socket.io

编辑:随着问题的本质变得更加清晰,更新了标题

我正在尝试实现一个非常简单的 socket.io 连接,以将广播事件从 Flask 服务器发送到 Javscript 客户端。第一条服务器消息到达客户端,但仅此而已。在服务器端,它不断调用emit并定期更新数据,但客户端在第一个消息之后再也不会收到任何消息。

这是 JavaScript 客户端(从 React 应用程序中提取的相关行):

var io=require('socket.io-client')
var socket = io.connect();
socket.on('connect', function() {
   console.log('Connection established');
});


socket.on('message', function(data){
   console.log('Message received');
   console.log(data);
   //only gets called for the first message sent by the server
}
Run Code Online (Sandbox Code Playgroud)

Flask 服务器代码:

from flask_socketio import SocketIO, emit
app = Flask(...)
socketio = SocketIO(app, async_mode="eventlet")
socketio.emit('message', "Test data", broadcast=True)

#Update function called periodically with JSON data
#of the form {"data": {...}}
def update(data):
    data = json.dumps(data)
    socketio.emit('message', data, broadcast=True)
Run Code Online (Sandbox Code Playgroud)

客户端收到“测试数据”消息,但没有从函数内部发送的任何消息update

编辑:我在 /usr/lib/python2.7/site-packages/socketio/base_manager.py 中找到此代码

for sid in self.get_participants(namespace, room):
            if sid != skip_sid:
                if callback is not None:
                    id = self._generate_ack_id(sid, namespace, callback)
                else:
                    id = None
                self.server._emit_internal(sid, event, data, namespace, id)
Run Code Online (Sandbox Code Playgroud)

在调试器中,当服务器发送原始“测试数据”以及发送后续更新时,我看到代表 socket.io 客户端的 sid 值。因此,服务器仍然将客户端视为参与者,具有与开始时相同的 ID,但客户端不会收到任何后续更新。如果我在更新函数发出任何事件之前连续发出两条消息,客户端就会收到它们。但是客户端不会接收更新函数内发出的任何事件。

我认为这是某种范围问题,但是如果在更新方法内发出事件时服务器仍然将客户端视为参与者,则似乎不存在范围问题。我还尝试了一个答案中的建议,将socketio对象传递给更新函数,并且得到了相同的行为。我不明白为什么客户端不会仅仅因为服务器从特定函数发送事件而接收事件,而该函数的执行上下文显示客户端仍然是参与者。

这是我能想到的最简单的示例,我正在做与我在网上看到的每个示例中看到的相同的事情。显然,我错过了一些东西。

Mid*_*ava 5

当我在 Flask 服务器上创建 SocketIO 实例时,我可以通过将 async_mode 设置为 True 来使其工作。

也就是说,我socketio = SocketIO(app, async_mode="eventlet")改为socketio = SocketIO(app, async_mode="threading")

我不知道为什么它不能与 eventlet 一起正常工作,这似乎是首选模式,因为根据文档字符串,如果您不指定它,线程是最后一个尝试的模式。

threading如果我更准确地理解其他异步模式之间的实现差异,也许我可以弄清楚为什么它仅在我使用文档所说的性能最低的模式时才有效。也许我错过了,但我在文档中没有看到这样的解释,只是对不同模式之间依赖差异的模糊讨论。