web-dev-qa-db-ja.com

Python:なんらかの理由でソケットが切断されたことを検出しますか?

私はPython 2.7.5で生のソケットインターフェイスを使用してアプリを書いています(import socket)。

TCPソケット接続がまだ接続および確立されている場合に、何らかのイベントを登録する方法、または定期的に簡単にテストする方法があるかどうかを知る必要があります。

私が見つけたアドバイスのほとんどは、「そこから読み取ろうとするだけです。閉じていると、エラーが発生するか、バイトが返されません」などのようなものです。ただし、そこからreadする準備ができていない場合もありますが、ソケットが閉じているかどうかを知りたいので、たとえば手動ですぐに再接続できます。

また、ソケットからreadingを実行すると、バッファから読み取られたバイトが削除されるため、単にreadingを使用して接続の「活性」をテストすることは現実的ではないようです。

接続の活性をチェックするバックグラウンドスレッドがあれば、私には問題ありません。そのスレッドは、接続がライブであるかどうかを確認するために毎秒1回言うことをチェックできます。ドロップされた場合は、関数を呼び出したり、変数などを設定して、接続が閉じられたことをアプリが認識できるようにします。なぜ閉じたのか(ピアによるリセット、タイムアウトなど)を知っているとさらに便利です。

これについて何かアドバイスはありますか?

20
fdmillion

このチュートリアルが推奨するようにselectを使用してください http://docs.python.org/2/howto/sockets.html#non-blocking-sockets

ソケットが出力可読リストにある場合、そのソケットでの受信が何かを返すという、特定のビジネスに近いことができます。書き込み可能なリストについても同じ考えです。あなたは何かを送ることができるでしょう。たぶんあなたが望むすべてではないかもしれませんが、何かが何もないよりましです。 (実際には、適度に健全なソケットは書き込み可能として返されます-送信ネットワークバッファスペースが利用できることを意味します。)

...ソケットのこれらの入力リストのどこかに厄介な死を遂げたものがある場合、選択は失敗します。

これは私が通常使うフローです

import select
import socket

ip = '127.0.0.1'
port = 80

conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect((ip, port))

while True:
    try:
        ready_to_read, ready_to_write, in_error = \
            select.select([conn,], [conn,], [], 5)
    except select.error:
        conn.shutdown(2)    # 0 = done receiving, 1 = done sending, 2 = both
        conn.close()
        # connection error event here, maybe reconnect
        print 'connection error'
        break
    if len(ready_to_read) > 0:
        recv = conn.recv(2048)
        # do stuff with received data
        print 'received:', recv
    if len(ready_to_write) > 0:
        # connection established, send some stuff
        conn.send('some stuff')
19
Steve Zhan