Comment définir le délai d'expiration du socket en Ruby?
-
04-07-2019 - |
Question
Comment définissez-vous le délai d'expiration des opérations de blocage sur un socket Ruby?
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.