Necesito establecer el tiempo de espera en el método de recepción de socket de Python. ¿Cómo hacerlo?
Necesito establecer el tiempo de espera en el método de recepción de socket de Python. ¿Cómo hacerlo?
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 que recv()
nunca se bloqueará indefinidamente. select()
también se puede utilizar para esperar en más de un socket a la vez.
import select
mysocket.setblocking(0)
ready = select.select([mysocket], [], [], timeout_in_seconds)
if ready[0]:
data = mysocket.recv(4096)
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.
select
es bueno, pero la parte en la que dices "no puedes" es engañosa, ya que la hay socket.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 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.
ready[0]
Solo sería falso si no hay cuerpo en la respuesta del servidor?
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()
y socket.settimeout()
funcionarán.
Tenga en cuenta que es posible que deba llamar settimeout
dos veces para sus necesidades, por ejemplo
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()
más de una vez, puede llamar al setdefaulttimeout()
método en primer lugar.
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.
Si implementa el lado del cliente, sería simple.
sock.connect(server_address)
sock.settimeout(3)
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 bytes
except socket.timeout: # fail after 1 second of no activity
print("Didn't receive data! [Timeout]")
finally:
s.close()
¡¡Espero que esto ayude!!
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.
intente esto, utiliza el C.
timeval = struct.pack('ll', 2, 100)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)
SO_RCVTIMEO
y SO_SNDTIMEO
.
2
y por qué 100
? ¿Cuál es el valor del tiempo de espera? En que unidad
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
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:
.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)