Захват события отключения клиента! - Gevent / Python - PullRequest
7 голосов
/ 26 июля 2010

Я использую длительный опрос для чата с gevent. Я использую Event.wait (), когда жду новых сообщений, которые будут опубликованы в чате.


Я бы хотел обработать случай, когда клиент отключил с некоторыми функциями:

например, Возврат "клиент отключился" как сообщение для других пользователей чата


Возможно ли это?=)

Ответы [ 3 ]

3 голосов
/ 15 октября 2012

Согласно 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()

Однако, есть ошибка в реализации Python wsgiref (и в сервере разработки Django, который наследует от него), который предотвращает вызов close () в серединеклиент потока отключается.Поэтому в этом случае следует избегать использования wsgiref и сервера разработки Django.

Обратите внимание, что close () не будет запущен сразу после отключения клиента.Это произойдет, когда вы попытаетесь написать какое-то сообщение клиенту и потерпите неудачу, потому что соединение больше не существует.

1 голос
/ 27 июля 2010

Это зависит от того, какой сервер WSGI вы используете.AFAIK gevent.wsgi не будет уведомлять ваш обработчик, когда клиент закрывает соединение, потому что libevent-http этого не делает.Однако, с gevent.pywsgi это должно быть возможно.Вам, вероятно, потребуется запустить дополнительный гринлет, чтобы отслеживать состояние сокета и каким-то образом уведомить гринлет, который запускает обработчик, например, убив его.Хотя я мог бы упустить более простой способ сделать это.

1 голос
/ 26 июля 2010

Это полный удар в темноте, так как я никогда не использовал gevent, но клиент не будет отключаться, если будет закрыт сокет. Так что, может быть, что-то вроде этого будет работать:

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