Domanda

Come si imposta il timeout per le operazioni di blocco su un socket Ruby?

È stato utile?

Soluzione

La soluzione che ho trovato che sembra funzionare è utilizzare Timeout :: timeout :

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

Altri suggerimenti

L'oggetto timeout è una buona soluzione.

Questo è un esempio di I / O asincrono (di natura non bloccante e si verifica in modo asincrono a il flusso dell'applicazione.)

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

Può essere usato per ottenere lo stesso effetto.

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

Penso che l'approccio non bloccante sia la strada da percorrere.
Ho provato l'articolo sopra citato e riuscivo ancora a bloccarlo.
questo articolo networking non bloccante e jonke's l'approccio sopra mi ha portato sulla strada giusta. Il mio server si stava bloccando sulla connessione iniziale, quindi avevo bisogno che fosse un livello leggermente inferiore.
il socket rdoc può fornire maggiori dettagli in 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

per ottenere un buon test. avviare un server socket semplice e quindi fare un ctrl-z per lo sfondo

IO.select si aspetta che i dati entrino nel flusso di input entro 10 secondi. questo potrebbe non funzionare se non è così.

Dovrebbe essere un buon sostituto del metodo aperto del TCPSocket.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top