我处于收到来自客户的消息的情况。在处理该请求的函数(@socketio.on)中,我想调用一个完成一些繁重工作的函数。这不应导致阻塞主线程,并且认为一旦工作完成就会通知客户端。因此,我开始了一个新线程。
现在我遇到了一个非常奇怪的行为:消息永远不会到达客户端。但是,代码会到达发送消息的特定位置。更令人惊讶的是,如果线程中除了发送给客户端的消息之外什么都没有发生,那么答案实际上会到达客户端。
总结一下:如果在发送消息之前发生了计算密集型的事情,那么它就不会被传递,否则就是。
在此之前显示的所有示例中,服务器响应客户端发送的事件。但是对于某些应用程序,服务器需要是消息的发起者。这对于向客户端发送源自服务器的事件的通知非常有用,例如在后台线程中。
这是一个示例代码。删除注释锐利 (#) 时,消息('foo from thread')不会找到到达客户端的方式,否则会。
from flask import Flask
from flask.ext.socketio import SocketIO, emit
app = Flask(__name__)
socketio = SocketIO(app)
from threading import Thread
import time
@socketio.on('client command')
def response(data):
thread = Thread(target = testThreadFunction)
thread.daemon = True
thread.start()
emit('client response', ['foo'])
def testThreadFunction():
# time.sleep(1)
socketio.emit('client response', ['foo from thread'])
socketio.run(app)
我正在使用 Python 3.4.3、Flask 0.10.1、flask-socketio1.2、eventlet 0.17.4。
该示例可以复制并粘贴到 .py 文件中,并且可以立即重现该行为。
有人可以解释这种奇怪的行为吗?
更新
这似乎是 eventlet 的错误。如果我做:
socketio = SocketIO(app, async_mode='threading')
尽管已安装它,但它强制应用程序不使用 eventlet。
但是,这对我来说不是一个适用的解决方案,因为使用“线程”作为 async_mode 拒绝接受二进制数据。每次我从客户端向服务器发送一些二进制数据时,它都会说:
WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance.
第三个选项,使用 gevent 作为 async_mode 对我不起作用,而且 gevent 还不支持 python 3。
那么还有其他建议吗?