Come posso impostare il timeout del socket in Ruby?
-
04-07-2019 - |
Domanda
Come si imposta il timeout per le operazioni di blocco su un socket Ruby?
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.