Pythonのソケットrecvメソッドにタイムアウトを設定する必要があります。どうやるか?
典型的なアプローチは、 select() を使用して、データが利用可能になるか、タイムアウトが発生するまで待機することです。データが実際に利用可能な場合にのみ、recv()
を呼び出します。安全にするために、recv()
が無期限にブロックされないように、ソケットを非ブロックモードに設定します。 select()
は、一度に複数のソケットで待機するためにも使用できます。
import select
mysocket.setblocking(0)
ready = select.select([mysocket], [], [], timeout_in_seconds)
if ready[0]:
data = mysocket.recv(4096)
開いているファイル記述子がたくさんある場合は、 poll() がselect()
のより効率的な代替手段です。
別のオプションは、socket.settimeout()
を使用してソケットのすべての操作のタイムアウトを設定することですが、別の答えでその解決策を明示的に拒否したことがわかります。
socket.settimeout()
があります
前述のように、 select.select()
と socket.settimeout()
の両方が機能します。
必要に応じてsettimeout
を2回呼び出す必要がある場合があることに注意してください。
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("",0))
sock.listen(1)
# accept can throw socket.timeout
sock.settimeout(5.0)
conn, addr = sock.accept()
# recv can throw socket.timeout
conn.settimeout(5.0)
conn.recv(1024)
応答を受信する前にタイムアウトを設定し、応答を受信した後にタイムアウトをNoneに戻すことができます。
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5.0)
data = sock.recv(1024)
sock.settimeout(None)
サーバー側を実装する場合、探しているタイムアウトは、プライマリソケットではなく接続ソケットのタイムアウトです。つまり、接続ソケットオブジェクトには別のタイムアウトがあります。これは、socket.accept()
メソッドの出力です。したがって:
sock.listen(1)
connection, client_address = sock.accept()
connection.settimeout(5) # This is the one that affects recv() method.
connection.gettimeout() # This should result 5
sock.gettimeout() # This outputs None when not set previously, if I remember correctly.
クライアント側を実装する場合、それは簡単です。
sock.connect(server_address)
sock.settimeout(3)
秒数を表す整数引数を受け入れるsocket.settimeout()
を使用できます。たとえば、socket.settimeout(1)
はタイムアウトを1秒に設定します
前の返信で述べたように、次のようなものを使用できます:.settimeout()
例:
import socket
s = socket.socket()
s.settimeout(1) # Sets the socket to timeout after 1 second of no activity
Host, port = "somehost", 4444
s.connect((Host, port))
s.send("Hello World!\r\n")
try:
rec = s.recv(100) # try to receive 100 bytes
except socket.timeout: # fail after 1 second of no activity
print("Didn't receive data! [Timeout]")
finally:
s.close()
これがお役に立てば幸いです!!
試してみて、基礎となるCを使用します。
timeval = struct.pack('ll', 2, 100)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)