Eu preciso definir o tempo limite no método de recv de soquete do python. Como fazer isso?
Eu preciso definir o tempo limite no método de recv de soquete do python. Como fazer isso?
Respostas:
A abordagem típica é usar select () para esperar até que os dados estejam disponíveis ou até que ocorra o tempo limite. Chame apenas recv()
quando os dados estiverem realmente disponíveis. Para ser seguro, também configuramos o soquete para o modo sem bloqueio para garantir que recv()
nunca será bloqueado indefinidamente. select()
também pode ser usado para aguardar em mais de um soquete de cada vez.
import select
mysocket.setblocking(0)
ready = select.select([mysocket], [], [], timeout_in_seconds)
if ready[0]:
data = mysocket.recv(4096)
Se você tiver muitos descritores de arquivo abertos, poll () é uma alternativa mais eficiente ao select()
.
Outra opção é definir um tempo limite para todas as operações no soquete usando socket.settimeout()
, mas vejo que você rejeitou explicitamente essa solução em outra resposta.
select
é bom, mas a parte em que você diz "você não pode" é enganosa, pois existe socket.settimeout()
.
select
- se você estiver executando em uma máquina Windows, use select
a biblioteca WinSock, que tem o hábito de retornar assim que alguns dados chegam, mas não necessariamente todos . Portanto, você precisa incorporar um loop para continuar chamando select.select()
até que todos os dados sejam recebidos. Como você sabe que obteve todos os dados (infelizmente) depende de você descobrir - pode significar procurar por uma string de terminador, um certo número de bytes ou apenas esperar por um tempo limite definido.
ready[0]
só será falsa se não há nenhum corpo na resposta do servidor?
select
é preferida quando esta solução é um liner (mais fácil de manter, menos risco na implementação incorreta) e usa select under the capô (implementação é a mesma que a resposta @DanielStuzbach).
Conforme mencionado, ambos select.select()
e socket.settimeout()
irão funcionar.
Observe que você pode precisar ligar settimeout
duas vezes para atender às suas necessidades, por exemplo
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)
.settimeout()
mais de uma vez, você pode chamar o setdefaulttimeout()
método em primeiro lugar.
O tempo limite que você está procurando é o tempo limite do soquete de conexão e não o do soquete primário, se você implementar o lado do servidor. Em outras palavras, há outro tempo limite para o objeto de soquete de conexão, que é a saída do socket.accept()
método. Portanto:
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.
Se você implementar o lado do cliente, seria simples.
sock.connect(server_address)
sock.settimeout(3)
Conforme mencionado nas respostas anteriores, você pode usar algo como: .settimeout()
Por exemplo:
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()
Eu espero que isso ajude!!
Você pode usar o socket.settimeout()
qual aceita um argumento inteiro que representa o número de segundos. Por exemplo, socket.settimeout(1)
definirá o tempo limite para 1 segundo
tente fazer isso, ele usa o C.
timeval = struct.pack('ll', 2, 100)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)
SO_RCVTIMEO
e SO_SNDTIMEO
.
2
e por quê 100
? Qual é o valor do tempo limite? Em qual unidade?
timeval = struct.pack('ll', sec, usec)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)
usec = 10000 significa 10 ms
#! /usr/bin/python3.6
# -*- coding: utf-8 -*-
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.settimeout(5)
PORT = 10801
s.bind(('', PORT))
print('Listening for broadcast at ', s.getsockname())
BUFFER_SIZE = 4096
while True:
try:
data, address = s.recvfrom(BUFFER_SIZE)
except socket.timeout:
print("Didn't receive data! [Timeout 5s]")
continue
Grite para: https://boltons.readthedocs.io/en/latest/socketutils.html
Ele fornece um soquete com buffer, que fornece muitas funcionalidades muito úteis, como:
.recv_until() #recv until occurrence of bytes
.recv_closed() #recv until close
.peek() #peek at buffer but don't pop values
.settimeout() #configure timeout (including recv timeout)