以下情况:
socketio
侦听传入消息(= JavaScript)。flask-socketio
和eventlet
发送数据(= Python)。如果客户端向服务器发送消息,则一切正常。服务器收到消息。示例:
socketio = SocketIO(app, engineio_logger=True, async_mode="eventlet")
@socketio.on("mymsg")
def handle_event(message):
print("received message: " + str(message))
不幸的是,在某种程度上,另一种方法不起作用。我有一个线程会在Web前端每秒显示大约5到10次的实时数据。它应该发送给客户端。
第一:如果产生数据的线程试图直接调用sockeito.emit()
,则根本不起作用。对于我来说,其原因尚不清楚,但可以理解为flask-socketio
与eventlet
遵循不同的异步模型,如文档所述。
第二个:将经典线程从flask / eventlet的异步模型中解耦到一定程度。我尝试为此使用eventlet
队列。我的线程产生的所有状态数据都将像这样放入队列:
statusQueue.put(statusMsg)
这很好。调试消息显示该操作始终执行,将数据添加到队列之后。
正如flasks的文档所述,建议我使用socketio.start_background_task()
来获得与socketio
所用异步模型兼容的运行线程。所以我在用这段代码:
def emitStatus():
print("Beginning to emit ...")
while True:
msg = statusQueue.get()
print("Sending status packet: " + str(msg))
socketio.emit("status", msg, broadcast=True)
statusQueue.task_done()
print("Sending status packet done.")
print("Terminated.")
socketio.start_background_task(emitStatus)
我要您寻求帮助的奇怪之处在于:第一次调用statusQueue.get()
时会阻塞,因为最初队列是空的。第一条消息从队列中取出,并通过socketio
发送。客户端上的调试消息表明Web客户端收到此消息。服务器上的调试消息表明消息已成功发送。但是:只要下一个statusQueue.get()
被调用,该调用就会无限期地阻塞,而不管队列中有多少消息。
我不确定这是否有帮助,但不确定其他一些信息:socketio
通讯是否完好无损。如果客户端发送数据,则一切正常。另外,我可以看到客户端和服务器都在打乒乓球以保持连接畅通。
我的问题是:如何正确实现能够异步向客户端发送消息的服务器?
请查看https://github.com/jkpubsrc/experiment-python-flask-socketio,以一个具有Python-Flask服务器进程和基于JQuery的JavaScript客户端的简约代码示例。
(仅供参考:由于这些是状态消息,不一定每条消息都需要到达。但是我非常希望至少收到一些消息,不仅是第一条消息,然后是其他消息。)
感谢您的回复。
答案 0 :(得分:0)
我留下了两种解决方案,以使代码可以作为请求请求使用。
基本上,答案是:您选择一种技术并坚持使用它:
async_mode=threading
吗?很好,请使用stdlib Queue。除非必须,否则不要导入eventlet。async_mode=eventlet
吗?也很棒,请使用eventlet Queue,不要忘记stdlib time.sleep
或socket
IO会阻止其他所有内容,并使用eventlet.monkey_patch()
凭借对eventlet和本机线程的充分了解,您可以将它们仔细地混合到工作代码中。就像您已经发现的那样,截至2018-09年,混音无法以友好的明显方式进行。抱歉。欢迎打补丁。