2010-07-26 14 views
7

Używam długiego sondowania do czatu z geventem. Korzystam z Event.wait() podczas oczekiwania na publikowanie nowych wiadomości na czacie.Przechwytywanie zdarzenia rozłączenia klienta! - Gevent/Python


Chciałbym obsłużyć okazji klient rozłącza z niektórych funkcji:

np Powrót „klient odłączony” jako wiadomość dla innych użytkowników czatu


Czy to możliwe? =)

Odpowiedz

1

Zależy to od używanego serwera WSGI. AFAIK gevent.wsgi nie powiadomi twojego handlera w żaden sposób, gdy klient zamknie połączenie, ponieważ libevent-http tego nie robi. Jednak w przypadku gevent.pywsgi powinno być możliwe. Najprawdopodobniej konieczne będzie uruchomienie dodatkowej zielonej kontrolki, aby monitorować stan gniazda i jakoś powiadomić greenlet, który uruchamia procedurę obsługi, np. zabijając go. Być może brakuje mi prostszego sposobu na zrobienie tego.

+0

Dziękuję bardzo za twoją myśl, naprawdę to doceniam. To jest coś, co NAPRAWDĘ chciałbym wiedzieć! =) #gevent na freenode wydaje się obecnie dość cichy ... Dzięki za odpowiedź denis! – RadiantHex

+0

Zastanawiam się, byłoby to straszne pomysł, aby podnieść jakiś wyjątek w aplikacji WSGI asynchronicznie, jeśli klient został rozłączony? –

1

To jest całkowite ukłucie w ciemności, ponieważ nigdy nie używałem geventa, ale klient nie odłączyłby się po prostu, gdy gniazdo jest zamknięte. Może więc coś takiego zadziała:

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

Mogłeś uderzyć ninja tym pchnięciem, pozwól mi sprawdzić! = D Dzięki za to! – RadiantHex

3

Zgodnie z WSGI PEP, jeśli aplikacja zwraca iterator metodą close(), serwer powinien wywołać to na końcu żądania. Oto przykład:

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

Istnieje jednak a bug w realizacji wsgiref Pythona (i na serwerze dev Django, która dziedziczy z nim), który zapobiega close() przed wezwał połowy strumienia rozłącza klienta. Dlatego też należy unikać wsgiref i serwera Django dla tego przypadku.

Należy również zauważyć, że funkcja close() nie zostanie uruchomiona natychmiast po rozłączeniu klienta. Stanie się tak, gdy spróbujesz napisać wiadomość do klienta i nie powiedzie się, ponieważ połączenie już nie istnieje.