2008-10-23 9 views
19

¿Cómo se configura el tiempo de espera para las operaciones de bloqueo en un socket Ruby?¿Cómo configuro el tiempo de espera del socket en Ruby?

+2

Encontré una solución mucho mejor que la aceptada aquí: http://stackoverflow.com/a/12111120/216314 –

+0

http://ruby-doc.org/stdlib/libdoc/timeout/rdoc/Timeout.html –

+0

[Módulo de tiempo de espera con bloqueos exclusivos] (http://stackoverflow.com/a/15304835/1301972). –

Respuesta

17

La solución que encontré lo que parece funcionar es utilizar Timeout::timeout:

require 'timeout' 
    ... 
begin 
    timeout(5) do 
     message, client_address = some_socket.recvfrom(1024) 
    end 
rescue Timeout::Error 
    puts "Timed out!" 
end 
+13

Usar tiempo de espera es un error. Debido a las barreras verdes, cualquier cosa que bloquee en IO bloqueará el hilo de tiempo de espera y evitará que funcione. – Sardathrion

+0

@Sardathrion, gracias por los comentarios, pero una solución sería mejor que un comentario negativo :) – Mike

+1

Los hilos de rubí están rotos, me temo. Encuentra un mejor idioma, duro pero cierto. – Sardathrion

15

El objeto de tiempo de espera es una buena solución.

Este es un ejemplo de E/S asíncrona (no bloqueo en la naturaleza y se produce de forma asíncrona a el flujo de la aplicación.)

IO.select(read_array 
[, write_array 
[, error_array 
[, timeout]]]) => array or nil 

Puede ser utilizado 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 
8

Creo que el enfoque no bloqueado es el camino a seguir.
Probé el artículo mencionado anteriormente y todavía podría hacer que cuelgue.
este artículo non blocking networking y el enfoque anterior de jonke me puso en el camino correcto. Mi servidor estaba bloqueando en la conexión inicial, así que necesitaba que fuera un nivel un poco más bajo.
la rdoc toma sea capaz de 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 conseguir una buena prueba. inicie un servidor de socket simple y luego haga un ctrl-z al fondo

el IO.select espera que los datos entren en el flujo de entrada en 10 segundos. esto puede no funcionar si ese no es el caso.

Debe ser un buen reemplazo para el método abierto de TCPSocket.

+0

Esto funciona muy bien para mí. Timeout no debe usarse bajo ninguna circunstancia debido a los hilos verdes de MRI. – Sardathrion

+2

Una conexión sin bloqueo aparece como escritura cuando está lista. Use 'IO.select (nil, [sock], nil, timeout.to_i)' – tmm1

+0

Solo funcionó para mí después de usar el comentario de tmm1. –

Cuestiones relacionadas