6

SSE を使用して新しいデータをクライアントにプッシュし、Flot(javascript グラフ作成ライブラリ) を使用して「ライブ」更新を表示することを考えています。私のサーバーはpython Flaskフレームワークで実行されており、データをクライアントにプッシュする方法を理解しましたが、ページを離れるとすぐに問題が発生します:

Exception happened during processing of request from ('127.0.0.1', 38814)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 582, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 323, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 640, in __init__
    self.finish()
  File "/usr/lib/python2.7/SocketServer.py", line 693, in finish
    self.wfile.flush()
  File "/usr/lib/python2.7/socket.py", line 303, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe

エラーが発生する理由を理解しています。「ライブ」データを提供する無限ループが原因で、ソケットが閉じられることはありません。質問は、ページの変更を検出してソケットをきれいに閉じるにはどうすればよいですか? クライアント側で接続を閉じることはできますか? ページの変更を検出するにはどうすればよいですか?

これはサーバー コードのスケルトンです。もちろん、テキスト メッセージを、表示するオブジェクトのリストを含む json に置き換えます。

def event_stream():
    import time
    while True:
        time.sleep(1)
        yield "data: This is a message number X.\n\n"

@app.route('/stream')
def stream():
    return Response(event_stream(), mimetype="text/event-stream")
4

4 に答える 4

2

私は汚れた (mokey パッチを含む) が、有効な解決策を見つけました。

接続が切断されたときに例外があるためSocketServer.StreamRequestHandler.finish、パッチを適用して例外をキャッチし、好きなように処理できます。

import socket
import SocketServer

def patched_finish(self):
    try:
        if not self.wfile.closed:
            self.wfile.flush()
            self.wfile.close()
    except socket.error:
        # Remove this code, if you don't need access to the Request object
        if _request_ctx_stack.top is not None:
            request = _request_ctx_stack.top.request
            # More cleanup code...
    self.rfile.close()

SocketServer.StreamRequestHandler.finish = patched_finish

対応するオブジェクトにアクセスする必要がある場合はRequest、さらにイベント ストリームを でラップする必要がありますflask.stream_with_context。私の場合は次のとおりです。

@app.route(url)
def method(host):
    return Response(stream_with_context(event_stream()),
                    mimetype='text/event-stream')

繰り返しますが、これは非常に汚い解決策であり、組み込みの WSGI サーバーを使用しないと機能しない可能性があります。

于 2014-04-29T14:16:38.917 に答える
2

これ以上の答えはありませんが、サーバーへの上記の ajax リクエストは良くないと思います。

フラスコでは、SSE は Response オブジェクトでストリーミングを使用します。Response で切断またはパイプの破損イベントを検出する方法がある場合は、ソケット イベントを処理し、割り当てられた他のリソースを解放することをお勧めします。

于 2013-08-19T23:26:54.720 に答える
0

prod 環境で Flask 内部開発 wsgi サーバーを使用しないでください。このソケットエラーをエレガントに処理できる uwsgi の使用を検討してください。

一方、壊れたこの sockrt もキャッチする python3 の使用について考えてみましょう。

于 2019-03-28T14:06:48.617 に答える