Para sua informação, se você escolher usar tempos limite ... você precisa saber como lidar com o tempo limite. esta pergunta do SO fala sobre como lidar quando ocorre um tempo limite: stackoverflow.com/questions/16745409
Trevor Boyd Smith
Respostas:
126
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.
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.
usar selecté bom, mas a parte em que você diz "você não pode" é enganosa, pois existe socket.settimeout().
nosklo
1
Está melhor agora, mas não vejo onde a resposta foi "rejeitada explicitamente".
nosklo
7
Um cuidado ao usar select- se você estiver executando em uma máquina Windows, use selecta 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.
JDM de
4
Por que é necessário definir o soquete sem bloqueio? Não acho que isso importe para a chamada select (e ela bloqueia até que um descritor possa ser lido ou o tempo limite expire, neste caso) e o recv () não bloqueará se o select for satisfeito. Eu tentei usando recvfrom () e parece funcionar corretamente sem setblocking (0).
HankB
1
Será que ready[0]só será falsa se não há nenhum corpo na resposta do servidor?
Ele não atinge o tempo limite de recepção (pelo menos quando eu tentei). Apenas o aceitar () expirou.
Oren S
9
O socket.recv () parece expirar para mim muito bem depois de definir socket.settimeout (), exatamente como pretendido. Eu estou inventando isso? Mais alguém pode confirmar isso?
Aeonaut
3
@Aeonaut Eu acho que isso atinge o tempo limite recv () na maioria das vezes, mas há uma condição de corrida. Em socket.recv () Python (2.6) chama select / poll internamente com o tempo limite e então recv () é chamado logo depois. Portanto, se você usar um soquete de bloqueio e entre essas 2 chamadas o outro ponto de extremidade travar, você pode acabar pendurado indefinidamente no recv (). Se você usar um soquete sem bloqueio, o python não chamará select.select internamente, então acho que a resposta de Daniel Stutzbach é a maneira correta.
emil.p.stanchev
4
Na verdade, eu provavelmente não entendi quando select () retorna, portanto, raspe o comentário anterior. O Guia de Beej diz que o acima é uma maneira válida de implementar um tempo limite no recv: beej.us/guide/bgnet/output/html/singlepage/… então, confio em uma fonte autorizada.
emil.p.stanchev
2
Não sei por que a solução que usa 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).
Acho que ele está entrando na mesma coisa que eu, onde não importa como você cutuque e cutuque essa função, ela trava. Tentei 2 ou 4 tempos limite agora e ainda trava. settimeout trava também.
Casey Daniel
1
Ao chamar .settimeout()mais de uma vez, você pode chamar o setdefaulttimeout()método em primeiro lugar.
mvarge
12
Você pode definir o tempo limite antes de receber a resposta e, depois de receber a resposta, defini-lo novamente para Nenhum:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5.0)
data = sock.recv(1024)
sock.settimeout(None)
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.
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 bytesexcept socket.timeout:# fail after 1 second of no activityprint("Didn't receive data! [Timeout]")finally:
s.close()
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
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)
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 querecv()
nunca será bloqueado indefinidamente.select()
também pode ser usado para aguardar em mais de um soquete de cada vez.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.fonte
select
é bom, mas a parte em que você diz "você não pode" é enganosa, pois existesocket.settimeout()
.select
- se você estiver executando em uma máquina Windows, useselect
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 chamandoselect.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?há
socket.settimeout()
fonte
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()
esocket.settimeout()
irão funcionar.Observe que você pode precisar ligar
settimeout
duas vezes para atender às suas necessidades, por exemplofonte
.settimeout()
mais de uma vez, você pode chamar osetdefaulttimeout()
método em primeiro lugar.Você pode definir o tempo limite antes de receber a resposta e, depois de receber a resposta, defini-lo novamente para Nenhum:
fonte
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:Se você implementar o lado do cliente, seria simples.
fonte
Conforme mencionado nas respostas anteriores, você pode usar algo como:
.settimeout()
Por exemplo:Eu espero que isso ajude!!
fonte
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 segundofonte
tente fazer isso, ele usa o C.
fonte
SO_RCVTIMEO
eSO_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 msfonte
Grite para: https://boltons.readthedocs.io/en/latest/socketutils.html
Ele fornece um soquete com buffer, que fornece muitas funcionalidades muito úteis, como:
fonte