2010-07-26 22 views
7

J'utilise une longue interrogation pour discuter avec gevent. J'utilise Event.wait() en attendant que de nouveaux messages soient postés sur le chat.Capture d'événement de déconnexion du client! - Gevent/Python


Je voudrais gérer l'occasion d'un client débranche avec certaines fonctionnalités:

par exemple Retour "client a déconnecté" comme un message pour les autres utilisateurs de chat


Est-ce possible? =)

Répondre

1

Cela dépend du serveur WSGI que vous utilisez. AFAIK gevent.wsgi ne notifiera en aucun cas votre gestionnaire lorsque le client ferme la connexion, car libevent-http ne le fait pas. Cependant, avec gevent.pywsgi, cela devrait être possible. Vous aurez probablement besoin de démarrer un greenlet supplémentaire pour surveiller la condition de socket et notifier en quelque sorte le greenlet qui exécute le gestionnaire, par ex. en le tuant. Je pourrais manquer un moyen plus facile de le faire cependant.

+0

Merci beaucoup pour votre réflexion, je l'apprécie vraiment. C'est quelque chose que j'aimerais vraiment savoir! =) #gevent sur freenode semble assez silencieux ces jours-ci ... Merci pour votre réponse denis! – RadiantHex

+0

Je me demande, serait-ce une idée terrible d'élever une exception dans l'application WSGI de manière asynchrone si un client s'est déconnecté? –

1

Ceci est un coup de poignard total dans l'obscurité que je n'ai jamais utilisé gevent mais ne serait pas une déconnexion du client simplement lorsque le socket est fermé. Donc peut-être quelque chose comme ça fonctionnerait:

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

vous pourriez avoir frappé un ninja avec ce coup de poignard, laissez-moi vérifier! = D Merci pour ça! – RadiantHex

3

Selon le WSGI PEP, si votre application renvoie un itérateur avec une méthode close(), le serveur doit l'appeler à la fin de la requête. Voici un exemple:

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

Cependant, il y a a bug dans la mise en œuvre de wsgiref Python (et dans le serveur de dev Django qui hérite de lui) qui empêche close() d'être appelé client mi-parcours se déconnecte. Evitez donc wsgiref et le serveur de développement Django pour ce cas.

Notez également que close() ne sera pas déclenché immédiatement lorsque le client se déconnecte. Cela se produit lorsque vous essayez d'écrire un message au client et échouez car la connexion n'est plus là.