¿Cómo configuro el tiempo de espera del socket en Ruby?
-
04-07-2019 - |
Pregunta
¿Cómo establece el tiempo de espera para bloquear operaciones en un socket Ruby?
Solución
La solución que encontré que parece funcionar es usar Timeout :: tiempo de espera :
require 'timeout'
...
begin
timeout(5) do
message, client_address = some_socket.recvfrom(1024)
end
rescue Timeout::Error
puts "Timed out!"
end
Otros consejos
El objeto de tiempo de espera es una buena solución.
Este es un ejemplo de E / S asíncrona (sin bloqueo en la naturaleza y se produce de forma asíncrona para el flujo de la aplicación).
IO.select(read_array
[, write_array
[, error_array
[, timeout]]] ) => array or nil
Se puede utilizar para obtener el mismo efecto.
require 'socket'
strmSock1 = TCPSocket::new( "www.dn.se", 80 )
strmSock2 = TCPSocket::new( "www.svd.se", 80 )
# Block until one or more events are received
#result = select( [strmSock1, strmSock2, STDIN], nil, nil )
timeout=5
timeout=100
result = select( [strmSock1, strmSock2], nil, nil,timeout )
puts result.inspect
if result
for inp in result[0]
if inp == strmSock1 then
# data avail on strmSock1
puts "data avail on strmSock1"
elsif inp == strmSock2 then
# data avail on strmSock2
puts "data avail on strmSock2"
elsif inp == STDIN
# data avail on STDIN
puts "data avail on STDIN"
end
end
end
Creo que el enfoque de no bloqueo es el camino a seguir.
Probé el artículo mencionado anteriormente y aún así pude colgarlo.
este artículo no bloquear la red y el jonke El enfoque anterior me llevó por el camino correcto. Mi servidor estaba bloqueando en la conexión inicial, así que necesitaba un nivel más bajo.
el socket rdoc puede dar más detalles en el connect_nonblock
def self.open(host, port, timeout=10)
addr = Socket.getaddrinfo(host, nil)
sock = Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0)
begin
sock.connect_nonblock(Socket.pack_sockaddr_in(port, addr[0][3]))
rescue Errno::EINPROGRESS
resp = IO.select([sock],nil, nil, timeout.to_i)
if resp.nil?
raise Errno::ECONNREFUSED
end
begin
sock.connect_nonblock(Socket.pack_sockaddr_in(port, addr[0][3]))
rescue Errno::EISCONN
end
end
sock
end
para obtener una buena prueba. iniciar un servidor de socket simple y luego hacer un ctrl-z para ponerlo en segundo plano
IO.select espera que entren datos en el flujo de entrada en 10 segundos. Esto puede no funcionar si ese no es el caso.
Debería ser un buen reemplazo para el método abierto del TCPSocket.