使用bottle和gevent.wsgi响应客户端断开连接? [英] Responding to client disconnects using bottle and gevent.wsgi?

查看:98
本文介绍了使用bottle和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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆