Para su información, si elige usar tiempos de espera ... necesita saber cómo manejar el tiempo de espera. esta pregunta SO habla sobre el manejo cuando ocurre un tiempo de espera: stackoverflow.com/questions/16745409
Trevor Boyd Smith
Respuestas:
125
El enfoque típico es usar select () para esperar hasta que los datos estén disponibles o hasta que se agote el tiempo de espera. Solo llame recv()cuando los datos estén realmente disponibles. Para estar seguros, también configuramos el socket en modo sin bloqueo para garantizar que recv()nunca se bloqueará indefinidamente. select()también se puede utilizar para esperar en más de un socket a la vez.
Si tiene muchos descriptores de archivos abiertos, poll () es una alternativa más eficiente a select().
Otra opción es establecer un tiempo de espera para todas las operaciones en el socket que usan socket.settimeout(), pero veo que ha rechazado explícitamente esa solución en otra respuesta.
el uso selectes bueno, pero la parte en la que dices "no puedes" es engañosa, ya que la hay socket.settimeout().
nosklo
1
Es mejor ahora, pero no veo dónde la respuesta fue "rechazada explícitamente".
nosklo
7
Una advertencia sobre el uso select: si está ejecutando en una máquina con Windows, selectconfíe en la biblioteca WinSock, que tiene la costumbre de regresar tan pronto como llegan algunos datos, pero no necesariamente todos . Por lo que debe incorporar un bucle para seguir llamando select.select()hasta que se reciban todos los datos. Cómo saber que ha obtenido todos los datos depende de usted (desafortunadamente) de averiguarlo; puede significar buscar una cadena de terminación, una cierta cantidad de bytes o simplemente esperar un tiempo de espera definido.
JDM
4
¿Por qué es necesario configurar el socket sin bloqueo? No creo que eso importe para la llamada de selección (y se bloquea hasta que se puede leer un descriptor o el tiempo de espera expira en este caso) y recv () no se bloqueará si se satisface la selección. Lo probé usando recvfrom () y parece funcionar correctamente sin setblocking (0).
HankB
1
¿ ready[0]Solo sería falso si no hay cuerpo en la respuesta del servidor?
No agota el tiempo de recuperación (al menos cuando lo probé). Solo se agota el tiempo de aceptar ().
Oren S
9
El socket.recv () parece agotar el tiempo de espera para mí después de configurar socket.settimeout (), exactamente como se esperaba. ¿Me lo estoy inventando? ¿Alguien más puede confirmar esto?
Aeonaut
3
@Aeonaut Creo que esto se agota recv () la mayor parte del tiempo, pero hay una condición de carrera. En socket.recv () Python (2.6) llama a select / poll internamente con el tiempo de espera y luego recv () se llama inmediatamente después. Entonces, si usa un socket de bloqueo y entre estas 2 llamadas, el otro extremo falla, puede terminar colgando indefinidamente en recv (). Si usa un socket sin bloqueo, Python no llama a select.select internamente, así que creo que la respuesta de Daniel Stutzbach es la forma correcta.
emil.p.stanchev
4
En realidad, probablemente entendí mal cuando select () regresa, así que por favor, raspe el comentario anterior. Beej's Guide dice que lo anterior es una forma válida de implementar un tiempo de espera en recv: beej.us/guide/bgnet/output/html/singlepage/… así que confiaré en que es una fuente autorizada.
emil.p.stanchev
2
No estoy seguro de por qué selectse prefiere la solución que se usa cuando esta solución es de una sola línea (más fácil de mantener, menos riesgo de implementar mal) y usa select bajo el capó (la implementación es la misma que la respuesta de @DanielStuzbach).
Creo que se está metiendo en lo mismo que yo estoy donde no importa cómo empujes y pinches esta función que cuelga. He intentado 2 o 4 tiempos de espera ahora y todavía se cuelga. settimeout también se bloquea.
Casey Daniel
1
Si llama .settimeout()más de una vez, puede llamar al setdefaulttimeout()método en primer lugar.
mvarge
12
Puede establecer el tiempo de espera antes de recibir la respuesta y, después de recibir la respuesta, volver a establecerlo en Ninguno:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5.0)
data = sock.recv(1024)
sock.settimeout(None)
El tiempo de espera que está buscando es el tiempo de espera del socket de conexión, no el del socket principal, si implementa el lado del servidor. En otras palabras, hay otro tiempo de espera para el objeto de conector de conexión, que es la salida del socket.accept()método. Por lo tanto:
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.
Como se mencionó en respuestas anteriores, puede usar algo como: .settimeout()
Por ejemplo:
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()
Puede usar socket.settimeout()que acepta un argumento entero que representa el número de segundos. Por ejemplo, socket.settimeout(1)establecerá el tiempo de espera en 1 segundo.
Proporciona un zócalo con búfer, esto proporciona una gran cantidad de funciones muy útiles, 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)
Respuestas:
El enfoque típico es usar select () para esperar hasta que los datos estén disponibles o hasta que se agote el tiempo de espera. Solo llame
recv()
cuando los datos estén realmente disponibles. Para estar seguros, también configuramos el socket en modo sin bloqueo para garantizar querecv()
nunca se bloqueará indefinidamente.select()
también se puede utilizar para esperar en más de un socket a la vez.Si tiene muchos descriptores de archivos abiertos, poll () es una alternativa más eficiente a
select()
.Otra opción es establecer un tiempo de espera para todas las operaciones en el socket que usan
socket.settimeout()
, pero veo que ha rechazado explícitamente esa solución en otra respuesta.fuente
select
es bueno, pero la parte en la que dices "no puedes" es engañosa, ya que la haysocket.settimeout()
.select
: si está ejecutando en una máquina con Windows,select
confíe en la biblioteca WinSock, que tiene la costumbre de regresar tan pronto como llegan algunos datos, pero no necesariamente todos . Por lo que debe incorporar un bucle para seguir llamandoselect.select()
hasta que se reciban todos los datos. Cómo saber que ha obtenido todos los datos depende de usted (desafortunadamente) de averiguarlo; puede significar buscar una cadena de terminación, una cierta cantidad de bytes o simplemente esperar un tiempo de espera definido.ready[0]
Solo sería falso si no hay cuerpo en la respuesta del servidor?hay
socket.settimeout()
fuente
select
se prefiere la solución que se usa cuando esta solución es de una sola línea (más fácil de mantener, menos riesgo de implementar mal) y usa select bajo el capó (la implementación es la misma que la respuesta de @DanielStuzbach).Como se mencionó, ambos
select.select()
ysocket.settimeout()
funcionarán.Tenga en cuenta que es posible que deba llamar
settimeout
dos veces para sus necesidades, por ejemplofuente
.settimeout()
más de una vez, puede llamar alsetdefaulttimeout()
método en primer lugar.Puede establecer el tiempo de espera antes de recibir la respuesta y, después de recibir la respuesta, volver a establecerlo en Ninguno:
fuente
El tiempo de espera que está buscando es el tiempo de espera del socket de conexión, no el del socket principal, si implementa el lado del servidor. En otras palabras, hay otro tiempo de espera para el objeto de conector de conexión, que es la salida del
socket.accept()
método. Por lo tanto:Si implementa el lado del cliente, sería simple.
fuente
Como se mencionó en respuestas anteriores, puede usar algo como:
.settimeout()
Por ejemplo:¡¡Espero que esto ayude!!
fuente
Puede usar
socket.settimeout()
que acepta un argumento entero que representa el número de segundos. Por ejemplo,socket.settimeout(1)
establecerá el tiempo de espera en 1 segundo.fuente
intente esto, utiliza el C.
fuente
SO_RCVTIMEO
ySO_SNDTIMEO
.2
y por qué100
? ¿Cuál es el valor del tiempo de espera? En que unidadtimeval = struct.pack('ll', sec, usec)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)
usec = 10000 significa 10 msfuente
Grita a: https://boltons.readthedocs.io/en/latest/socketutils.html
Proporciona un zócalo con búfer, esto proporciona una gran cantidad de funciones muy útiles, como:
fuente