Pregunta

¿Cómo establece el tiempo de espera para bloquear operaciones en un socket Ruby?

¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top