2010-07-26 22 views
7

Estoy utilizando una encuesta larga para chatear con gevent. Estoy usando Event.wait() cuando espero que se publiquen nuevos mensajes en el chat.¡Evento de captura de la desconexión del cliente! - Gevent/Python


me gustaría manejar la ocasión un cliente se desconecta con algunas funciones:

por ejemplo, Volver "cliente ha desconectado" como un mensaje para otros usuarios del chat


Es esto posible? =)

Respuesta

1

Esto depende del servidor WSGI que use. AFAIK gevent.wsgi no notificará a su controlador de ninguna manera cuando el cliente cierre la conexión, porque libevent-http no hace eso. Sin embargo, con gevent.pywsgi debería ser posible. Probablemente necesite iniciar un greenlet adicional para monitorear la condición del zócalo y de alguna manera notificar al greenlet que ejecuta el manejador, p. matándolo. Sin embargo, me podría estar perdiendo una manera más fácil de hacer esto.

+0

Muchas gracias por su pensamiento, realmente lo aprecio. ¡Esto es algo que REALMENTE me encantaría saber! =) #gevent en freenode parece bastante silencioso en estos días ... Gracias por tu respuesta denis! – RadiantHex

+0

Me pregunto, ¿sería una idea terrible presentar alguna excepción en la aplicación WSGI de forma asincrónica si un cliente se desconecta? –

1

Esto es una puñalada total en la oscuridad ya que nunca he usado gevent pero no me desconectaría un cliente simplemente cuando el socket está cerrado. Entonces algo como esto funcionaría:

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

es posible que hayas golpeado a un ninja con esa puñalada, ¡déjame comprobar! = D Gracias por eso! – RadiantHex

3

Según el WSGI PEP, si su aplicación devuelve un iterador con un método close(), el servidor debería llamar al final de la solicitud. He aquí un ejemplo:

""" 
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() 

Sin embargo, hay a bug en aplicación wsgiref de Python (y en el servidor dev Django que herede de ella) que impide cerrar() de ser llamado en cliente se desconecta a mitad de camino. Así que evite wsgiref y el servidor de desarrollo Django para este caso.

Tenga en cuenta también que close() no se disparará inmediatamente cuando el cliente se desconecta. Sucederá cuando trates de escribir algún mensaje al cliente y falle porque la conexión ya no está allí.

Cuestiones relacionadas