1. ホーム
  2. python

[解決済み] python socket.settimeout()の正しい使い方

2022-02-15 23:21:39

質問

私が知っている限り、あなたが socket.settimeout(value) を呼び出すと、そのソケットは scocket.timeout を発生させます。 socket.recv は、指定された値よりも長い時間待機する必要があります。

しかし、大量のデータを受信する必要があり、そのために recv() この場合、settimeout はどのように影響するのでしょうか?

次のようなコードがあるとします。

to_receive = # an integer representing the bytes we want to receive
socket = # a connected socket

socket.settimeout(20)
received = 0
received_data = b""

while received < to_receive:
    tmp = socket.recv(4096)
    if len(tmp) == 0:
        raise Exception()
    received += len(tmp)
    received_data += tmp

socket.settimeout(None)

コードの3行目では、ソケットのタイムアウトを20秒に設定しています。このタイムアウトは反復処理ごとにリセットされるのでしょうか?その反復のうちの1つが20秒以上かかった場合にのみ、タイムアウトが発生するのでしょうか?

A) どうすれば、期待されるすべてのデータを受信するのに20秒以上かかっている場合に例外を発生させるように再コード化できますか?

B) データをすべて読み込んだ後、タイムアウトを None にしないと、何か悪いことが起こるのでしょうか?(接続はキープアライブで、将来さらにデータが要求される可能性があります)。

解決方法は?

タイムアウトが適用される 単独で は、ソケットの読み取り/書き込み操作の各呼び出しに使用されます。そのため、次に呼び出すと、また20秒になります。

A) タイムアウトを複数の結果的な呼び出しで共有するには、それを手動で追跡する必要があります。以下のようなものです。

deadline = time.time() + 20.0
while not data_received:
    if time.time() >= deadline:
        raise Exception() # ...
    socket.settimeout(deadline - time.time())
    socket.read() # ...

B) タイムアウトのあるソケットを使用していて、そのソケットを処理する準備ができていないコード socket.timeout 例外が発生した場合、失敗する可能性が高いです。操作を開始する前にソケットのタイムアウト値を記憶しておき、操作が終わったら復元する方が確実です。

def my_socket_function(socket, ...):
    # some initialization and stuff
    old_timeout = socket.gettimeout() # Save
    # do your stuff with socket
    socket.settimeout(old_timeout) # Restore
    # etc

こうすることで、あなたの関数は、呼び出したコードがソケットのタイムアウトをどのように処理しても、その機能に影響を与えることはありません。