2010-07-26 26 views
7

我使用长轮询与gevent聊天。我正在使用Event.wait()等待新消息发布到聊天中。捕获客户端断开事件! - Gevent/Python


我想处理之际客户端断开一些功能:

例如返回“客户端已断开连接”为其他聊天用户


这是可能的消息? =)

回答

1

这取决于你使用的WSGI服务器。当客户端关闭连接时,AFAIK gevent.wsgi不会以任何方式通知您的处理程序,因为libevent-http不会这样做。但是,使用gevent.pywsgi应该是可以的。您可能需要启动一个额外的greenlet来监视套接字条件,并以某种方式通知运行该处理程序的greenlet,例如通过杀死它。我可能会错过一个更简单的方法来做到这一点。

+0

非常感谢您的想法,我非常感谢。这是我真的很想知道的东西! =)#freenode在freenode这些天似乎很沉默...感谢您的回复denis! – RadiantHex 2010-07-26 21:56:13

+0

我想知道,如果客户端已断开连接,异步地在WSGI应用程序中引发一些异常,这会是一个糟糕的主意吗? – 2010-08-01 19:56:32

1

这是一个在黑暗中总刺,因为我从来没有使用过gevent,但不会客户端断开,只是当套接字关闭。所以也许这样的事情会起作用:

if not Event.wait(): 
    # Client has disconnected, do your magic here! 
    return Chat({'status': 'client x has disconnected'}) 
+0

你可能用这把刺击了一个忍者,让我检查! = D谢谢你! – RadiantHex 2010-07-26 13:12:13

3

按照WSGI PEP,如果您的应用程序返回一个迭代用close()方法,服务器应该调用在请求结束。这里有一个例子:

""" 
Run this script with 'python sleepy_app.py'. Then try connecting to the server 
with curl: 

    curl -N http://localhost:8000/ 

You should see a counter printed in your terminal, incrementing once every 
second. 

Hit Ctrl-C on the curl window to disconnect the client. Then watch the 
server's output. If running with a WSGI-compliant server, you should see 
"SLEEPY CONNECTION CLOSE" printed to the terminal. 
""" 

class SleepyApp(object): 
    def __init__(self, environ, start_response): 
     self.environ = environ 
     self.start_response = start_response 

    def __iter__(self): 
     self.start_response('200 OK', [('Content-type', 'text/plain')]) 
     # print out one number every 10 seconds. 
     import time # imported late for easier gevent patching 
     counter = 0 
     while True: 
      print "SLEEPY", counter 
      yield str(counter) + '\n' 
      counter += 1 
      time.sleep(1) 

    def close(self): 
     print "SLEEPY CONNECTION CLOSE" 


def run_gevent(): 
    from gevent.monkey import patch_all 
    patch_all() 
    from gevent.pywsgi import WSGIServer 
    server = WSGIServer(('0.0.0.0', 8000), SleepyApp) 
    print "Server running on port 0.0.0.0:8000. Ctrl+C to quit" 
    server.serve_forever() 

if __name__ == '__main__': 
    run_gevent() 

然而,有a bug在Python的执行的wsgiref(以及从它继承了Django的开发服务器),防止关闭()被调用上中游客户端断开连接。所以在这种情况下避免使用wsgiref和Django开发服务器。

还要注意,当客户端断开连接时close()不会立即被触发。当您尝试向客户端写入一些消息并因为连接不再存在而失败时,会发生这种情况。