Question

Comment définissez-vous le délai d'expiration des opérations de blocage sur un socket Ruby?

Était-ce utile?

La solution

La solution que j'ai trouvée et qui semble fonctionner consiste à utiliser Timeout :: délai d'expiration :

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

Autres conseils

L'objet de délai d'attente est une bonne solution.

Ceci est un exemple d'E / S asynchrone (de nature non bloquante et se produit de manière asynchrone à le flux de l'application.)

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

Peut être utilisé pour obtenir le même effet.

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

Je pense que l'approche non bloquante est la voie à suivre.
J'ai essayé l'article mentionné ci-dessus et je pouvais toujours le faire accrocher.
cet article non bloquant la mise en réseau et les jonke approche ci-dessus m'a mis sur le bon chemin. Mon serveur bloquait lors de la connexion initiale et il me fallait donc un niveau un peu plus bas.
le socket rdoc peut donner plus de détails dans le 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

pour faire un bon test. démarrer un serveur de socket simple et ensuite faire un ctrl-z pour le mettre en arrière-plan

IO.select s'attend à ce que les données arrivent dans le flux d'entrée dans les 10 secondes. cela peut ne pas fonctionner si ce n'est pas le cas.

Cela devrait bien remplacer la méthode ouverte de TCPSocket.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top