使用bottle和gevent.wsgi响应客户端断开连接? [英] Responding to client disconnects using bottle and gevent.wsgi?
问题描述
我有一个小型异步服务器,该服务器使用瓶和 gevent.wsgi 。在瓶装文件:
I have a small asynchronous server implemented using bottle and gevent.wsgi. There is a routine used to implement long poll that looks pretty much like the "Event Callbacks" example in the bottle documentation:
def worker(body):
msg = msgbus.recv()
body.put(msg)
body.put(StopIteration)
@route('/poll')
def poll():
body = gevent.queue.Queue()
worker = gevent.spawn(worker, body)
return body
在这里, msgbus
是ZMQ sub
套接字。
Here, msgbus
is a ZMQ sub
socket.
这一切都很好,但是如果客户端断开连接而
worker
在msgbus上受阻。 recv(),该greenlet任务将在永远附近挂起
(嗯,直到收到消息),并且只有
会在尝试断开连接的客户端时找到有关该客户端的信息发送
响应。
This all works fine, but if a client breaks the connection while
worker
is blocked on msgbus.recv()
, that greenlet task will hang
around "forever" (well, until a message is received), and will only
find out about the disconnected client when it attempts to send a
response.
如果我可以使用 msgbus.poll(timeout = something)
不要ant永远阻止
等待ipc消息,但我仍然无法检测到客户端
断开连接。
I can use msgbus.poll(timeout=something)
if I don't want to block
forever waiting for ipc messages, but I still can't detect a client
disconnect.
我想要的内容要做的就是获得对客户端
套接字的引用,以便我可以在 select
或 poll
循环,
或在我的greenlet中获取某种异步通知,但是
我不确定如何使用这些
框架来完成这两项工作(
What I want to do is get something like a reference to the client
socket so that I can use it in some kind of select
or poll
loop,
or get some sort of asynchronous notification inside my greenlet, but
I'm not sure how to accomplish either of these things with these
frameworks (bottle and gevent).
有没有办法通知客户端断开连接?
Is there a way to get notified of client disconnects?
推荐答案
啊哈! wsgi.input
变量(至少在 gevent.wsgi
下)具有 rfile
成员,它是一个类似文件的对象。 WSGI规范,因此它可能无法与其他服务器一起使用。
Aha! The wsgi.input
variable, at least under gevent.wsgi
, has an rfile
member that is a file-like object. This doesn't appear to be required by the WSGI spec, so it might not work with other servers.
通过此操作,我可以将代码修改为:
With this I was able to modify my code to look something like:
def worker(body, rfile):
poll = zmq.Poller()
poll.register(msgbus)
poll.register(rfile, zmq.POLLIN)
while True:
events = dict(poll.poll())
if rfile.fileno() in events:
# client disconnect!
break
if msgbus in events:
msg = msgbus.recv()
body.put(msg)
break
body.put(StopIteration)
@route('/poll')
def poll():
rfile = bottle.request.environ['wsgi.input'].rfile
body = gevent.queue.Queue()
worker = gevent.spawn(worker, body, rfile)
return body
这很好用...
...除非 OpenShift ,您必须在其中使用
端口8000上具有Websockets支持的备用前端。
...except on OpenShift, where you will have to use the alternate frontend on port 8000 with websockets support.
这篇关于使用bottle和gevent.wsgi响应客户端断开连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!