Set socket-timeout in Ruby über SO_RCVTIMEO socket-option

Ich versuche, mich sockets timeout in Ruby über die SO_RCVTIMEO socket-option, aber es scheint keinen Einfluss auf die aktuelle *nix Betriebssystem.

Mithilfe von Ruby ' s Timeout-Modul ist keine option, da es erfordert die Laich-und Fügeverfahren und-threads für jedes timeout, das kann teuer werden. In Anwendungen, die eine geringe socket-timeouts und die eine hohe Anzahl von threads, die es im wesentlichen tötet Leistung. Dies wurde festgestellt in vielen Orten, einschließlich - Stack Overflow.

Ich habe gelesen, Mike Perham ' s ausgezeichneten Beitrag zum Thema hier und zu einer Reduzierung des Problems auf eine Datei ausführbarer code erstellt ein einfaches Beispiel für einen TCP-server, der eine Anfrage erhalten, warten Sie die Zeit geschickt, in der Wunsch und dann die Verbindung schließen.

Erstellt der client einen socket, legt der receive-timeout auf 1 Sekunde, und dann eine Verbindung zum server herstellt. Der client teilt dem server mit, um die Sitzung schließen, nach 5 Sekunden wartet dann auf Daten.

Sollte der client timeout nach einer Sekunde sondern erfolgreich schließt die Verbindung nach 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

Habe ich versucht, das gleiche zu tun, mit ein TCPSocket (die automatisch eine Verbindung her) und habe ähnliche code in redis und andere Projekte.

Außerdem kann ich überprüfen, ob die option gesetzt wurde, durch den Aufruf getsockopt wie diese:

sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO).inspect

Nicht festlegen, an die dieser socket-option tatsächlich für jedermann?

  • Diese Art von Frage schon gepostet hat, bevor, und wie es scheint, die beste Antwort war der Einsatz von Ruby ' s timeout Bibliothek rund um die recv nennen.
  • Nein, mit der timeout-Bibliothek threads erstellt, so dass jedes timeout benötigt die Schaffung und die Zerstörung eines thread, das kann sehr teuer werden. Ich update meine Antwort zu reflektieren, dass es nicht effizient ist.
  • Sieben Jahre später, haben wir auch gelernt, dass es nicht nur ineffizient, sondern auch gefährlich.
InformationsquelleAutor Tyler Brock | 2012-03-24
Schreibe einen Kommentar