Sto provando a rendere il timeout dei socket in Ruby tramite l'opzione socket SO_RCVTIMEO, tuttavia sembra che non abbia alcun effetto su alcun sistema operativo * nix recente.Imposta il timeout del socket in Ruby tramite SO_RCVTIMEO opzione socket
L'utilizzo del modulo Timeout di Ruby non è un'opzione in quanto richiede spawn e unisce i thread per ciascun timeout che può diventare costoso. Nelle applicazioni che richiedono timeout di socket bassi e che hanno un numero elevato di thread, uccide essenzialmente le prestazioni. Questo è stato notato in molti posti tra cui Stack Overflow.
Ho letto l'eccellente post di Mike Perham sull'oggetto here e nel tentativo di ridurre il problema a un file di codice eseguibile creato un semplice esempio di un server TCP che riceverà una richiesta, attendi la quantità di tempo inviata nella richiesta e quindi chiudere la connessione.
Il client crea un socket, imposta il timeout di ricezione su 1 secondo e quindi si collega al server. Il client dice al server di chiudere la sessione dopo 5 secondi, quindi attende i dati.
Il cliente deve timeout dopo un secondo, ma invece chiude con successo la connessione dopo 5.
#!/usr/bin/env ruby
require 'socket'
def timeout
sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
# Timeout set to 1 second
timeval = [1, 0].pack("l_2")
sock.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, timeval
# Connect and tell the server to wait 5 seconds
sock.connect(Socket.pack_sockaddr_in(1234, '127.0.0.1'))
sock.write("5\n")
# Wait for data to be sent back
begin
result = sock.recvfrom(1024)
puts "session closed"
rescue Errno::EAGAIN
puts "timed out!"
end
end
Thread.new do
server = TCPServer.new(nil, 1234)
while (session = server.accept)
request = session.gets
sleep request.to_i
session.close
end
end
timeout
Ho provato a fare la stessa cosa con un TCPSocket così (che si connette automaticamente) e hanno visto codice simile in redis e altri progetti.
Inoltre, posso verificare che l'opzione è stata impostata chiamando getsockopt
come questo:
sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO).inspect
non impostare questa opzione presa in realtà il lavoro per chiunque?
Questo tipo di questione è stata postato prima, e sembra che la risposta migliore sia stata usare la libreria 'timeout' di Ruby attorno alla chiamata' recv'. – Linuxios
No, usare la libreria di timeout genera i thread in modo che ogni timeout richieda la creazione e la distruzione di un thread che può diventare molto costoso. aggiornerò la mia risposta per riflettere sul fatto che non è efficiente –