以下情况:
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))
不幸的是,反过来也行不通 - 在某种程度上。我有一个线程产生实时数据,每秒约5到10次Web前端应该显示。它应该发送给客户端。
第一:如果生成数据的线程试图直接调用sockeito.emit()
,它根本不起作用。其中的原因尚不清楚,但正如文件所述,flask-socketio
与eventlet
遵循不同的异步模型,但在某种程度上看似合理。
第二:将经典线程与flask / eventlet的异步模型分离在一定程度上起作用。我尝试使用eventlet
队列。我的线程产生的所有状态数据都放入队列中,如下所示:
statusQueue.put(statusMsg)
这很好用。调试消息显示此操作始终执行,将数据添加到队列之后。
由于烧瓶的文档告诉我,我建议使用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
通信完好无损。如果客户端发送数据,一切正常。此外,我可以看到客户端和服务器的ping-pongs一直保持连接活动。
我的问题是:如何正确实现能够异步向客户端发送消息的服务器?
查看https://github.com/jkpubsrc/experiment-python-flask-socketio,了解一个简单的代码示例,其中包含Python-Flask服务器进程和基于JQuery的JavaScript客户端。
(仅供参考:由于这些是状态消息,因此不一定每条消息都需要到达。但我非常希望至少收到一些消息,不仅是第一条消息,还有其他消息。)
谢谢你的回复。
我留下了两个解决方案,使代码可以作为拉取请求。
基本上,答案是:您选择一种技术并坚持使用它:
async_mode=threading
?太棒了,使用stdlib队列。除非必须,否则不要导入eventlet。async_mode=eventlet
?也很好,使用eventlet队列,不要忘记stdlib time.sleep
或socket
IO将阻止其他一切,修复eventlet.monkey_patch()
熟悉eventlet和本机线程,您可以仔细地将它们混合到工作代码中。正如您已经发现的那样,截至2018-09,混合不能以友好明显的方式起作用。抱歉。欢迎补丁。