你有two阻止您这样做的错误:
First,您正在尝试从套接字上下文外部使用 socket.io 发出事件。
当函数被包裹时@socketio.on
装饰器,它变成了Event-Handlers
。
当在服务器端触发事件时,它将搜索正确的处理程序来处理该事件并将上下文初始化为发出该事件的特定客户端。
如果没有初始化此上下文,您的socketio.emit('output', str(json), namespace='/chat')
不会执行任何操作,因为服务器不知道应该向谁发回响应。
无论如何,发出事件有一个小技巧manually to a 特定客户(即使您不在其上下文中)。每次打开套接字时,服务器都会将其分配给一个与套接字 id 同名的“私人”房间(sid
)。因此,为了从客户端上下文向外部发送消息,您可以创建一个已连接客户端 ID 的列表,并使用room=<id>
争论。
例如:
web_app.py:
...
from flask import Flask, request
clients = []
@socketio.on('connect')
def handle_connect():
print('Client connected')
clients.append(request.sid)
@socketio.on('disconnect')
def handle_disconnect():
print('Client disconnected')
clients.remove(request.sid)
def send_message(client_id, data):
socketio.emit('output', data, room=client_id)
print('sending message "{}" to client "{}".'.format(data, client_id))
...
那么你可能会按如下方式使用它:
main.py:
import web_app
import threading
import time
def main():
webapp_thread = threading.Thread(target=run_web_app)
webapp_thread.start()
while not web_app.clients:
print "waiting for client to connect"
time.sleep(1)
print "Connected..."
time.sleep(3)
print "Trying to print dummy message..."
web_app.send_message(web_app.clients[0], "Dummy")
...
但即使你尝试这样做,它也不会起作用(这给我们带来了第二个错误)。
Second,您将 eventlet 与常规 Python 线程混合在一起,这不是一个好主意。 eventlet 使用的绿色线程不能与常规线程很好地配合。相反,您应该使用绿色线程来满足所有线程需求。
我在互联网上找到的一种选择是对 Python 标准库进行猴子修补,以便将线程、套接字等替换为 eventlet 友好的版本。您可以在 main.py 脚本的最顶部执行此操作:
import eventlet
eventlet.monkey_patch()
之后它应该可以正常工作(我自己尝试过)。如果您还有其他问题,请告诉我...