Estoy intentando hacer que el socket expire en Ruby a través de la opción de socket SO_RCVTIMEO; sin embargo, parece que no tiene ningún efecto en ningún sistema operativo * nix reciente.Establecer el tiempo de espera del socket en Ruby mediante la opción de socket SO_RCVTIMEO
El uso del módulo de tiempo de espera de Ruby no es una opción, ya que requiere engendrar y unir hilos por cada tiempo de espera que puede llegar a ser costoso. En aplicaciones que requieren tiempos de espera de socket bajos y que tienen un alto número de subprocesos, esencialmente se mata el rendimiento. Esto se ha observado en muchos lugares, incluido Stack Overflow.
He leído excelente publicación de Mike Perham sobre el tema here y en un esfuerzo por reducir el problema a un archivo de código ejecutable creado un ejemplo simple de un servidor TCP que recibirá una solicitud, espere el tiempo enviado en la solicitud y luego cierre la conexión.
El cliente crea un socket, establece el tiempo de espera de recepción de 1 segundo y luego se conecta al servidor. El cliente le dice al servidor que cierre la sesión después de 5 segundos y luego espera datos.
El cliente debe tiempo de espera después de un segundo, pero en su lugar se cierra con éxito la conexión después de 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
He intentado hacer lo mismo con un TCPSocket así (que se conecta de forma automática) y han visto un código similar en redis y otros proyectos.
Además, puedo comprobar que la opción se ha establecido llamando getsockopt
así:
sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO).inspect
lo hace configurar esta opción toma realmente funciona para cualquier persona?
Este tipo de pregunta ha sido publicado antes, y parece que la mejor respuesta fue utilizar la biblioteca 'timeout' de Ruby alrededor de la llamada' recv' – Linuxios
No, el uso de la biblioteca de tiempo de espera genera hilos de modo que cada tiempo de espera requiere crear y destruir un hilo que puede ser muy costoso. actualizaré mi respuesta para reflejar que no es eficiente. –