7

gevent とのチャットにロング ポーリングを使用しています。新しいメッセージがチャットに投稿されるのを待っているときに Event.wait() を使用しています。


クライアントがいくつかの機能で切断する機会を処理したいと思います:

例:他のチャット ユーザーへのメッセージとして「クライアントが切断されました」を返す


これは可能ですか?=)

4

3 に答える 3

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

ただし、Python の wsgiref 実装 (およびそれを継承する Django 開発サーバー) には、ストリームの途中でクライアントが切断されたときに close() が呼び出されないようにするバグがあります。したがって、この場合は wsgiref と Django dev サーバーを使用しないでください。

また、クライアントが切断されたときに close() がすぐに起動されないことにも注意してください。クライアントにメッセージを書き込もうとして、接続が失われたために失敗した場合に発生します。

于 2012-10-15T02:25:46.163 に答える
1

これは、使用するWSGIサーバーによって異なります。aFAIK gevent.wsgiは、クライアントが接続を閉じたときにハンドラーに通知しません。これは、libevent-httpが通知を行わないためです。ただし、gevent.pywsgiを使用すると、それが可能になるはずです。ソケットの状態を監視するために追加のグリーンレットを開始し、ハンドラーを実行するグ​​リーンレットに何らかの方法で通知する必要があります。たとえば、それを強制終了します。しかし、これを行うためのより簡単な方法が欠けている可能性があります。

于 2010-07-26T20:55:49.620 に答える
1

私は gevent を使用したことがないので、これは闇の中での完全な刺し傷ですが、ソケットが閉じられたときにクライアントが切断されることはありません。したがって、次のようなものが機能する可能性があります。

if not Event.wait():
    # Client has disconnected, do your magic here!
    return Chat({'status': 'client x has disconnected'})
于 2010-07-26T13:02:58.243 に答える