2008-10-23 16 views
19

Bir Ruby soketindeki işlemleri engellemek için zaman aşımını nasıl ayarlarsınız?Yuva zaman aşımını Ruby'de nasıl ayarlayabilirim?

+2

Kabul edileninizden çok daha iyi bir çözüm buldu: http://stackoverflow.com/a/12111120/216314 –

+0

http://ruby-doc.org/stdlib/libdoc/timeout/rdoc/Timeout.html –

+0

[Özel kilitler ile zaman aşımı modülü] (http://stackoverflow.com/a/15304835/1301972). –

cevap

17

çalışması için görünür buldum çözümü Timeout::timeout kullanmaktır:

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

Zaman aşımı kullanmak bir hatadır. Yeşil çadırlar nedeniyle, IO üzerinde bloke olan her şey zaman aşımı ipini de engelleyecek ve böylece çalışmayı durduracaktır. – Sardathrion

+0

@Sardathrion, geri bildirim için teşekkürler, ancak bir çözüm, olumsuz bir yorumdan daha iyi olurdu :) – Mike

+1

Ruby thread'ler bozuk Korkarım. Daha iyi bir dil bulun - sert ama doğru. – Sardathrion

15

zaman aşımı nesne iyi bir çözümdür.

Bu uyumsuz I/O örneğidir (doğada engellenmeyen ve zaman uyumsuz uygulama akışının meydana gelir.)

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

aynı etkiyi elde etmek için kullanılabilir.

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 
8

Engellemeyi engelleyen yaklaşımın yol olduğunu düşünüyorum.
Yukarıdaki makaleyi denedim ve hala askıya alabilirim.
Bu makale non blocking networking ve yukarıda jonke'nin yaklaşımı beni doğru yolda buldu. Sunucum ilk bağlantıda engellendi, bu yüzden biraz daha düşük bir seviyeye ihtiyacım vardı.
soket rdoc iyi testi yaptırmak 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 

içine daha ayrıntılı bilgi verebilir. basit bir soket sunucusunu başlatın ve daha sonra arka plan için bir ctrl-z yapın.

IO.select, 10 saniye içinde giriş akışında veri gelmesini bekler. Bu durum böyle değilse çalışmayabilir.

TCPSocket'in açık yöntemi için iyi bir yedek olmalıdır.

+0

Bu benim için çok iyi çalışıyor. MRG'nin yeşil dişleri nedeniyle zaman aşımı hiçbir koşulda kullanılmamalıdır. – Sardathrion

+2

Bloke olmayan bir bağlantı hazır olduğunda yazılabilir. 'IO.select'i kullanın (nil, [çorap], nil, timeout.to_i)' – tmm1

+0

Sadece tmm1'in yorumunu kullandıktan sonra benim için çalıştım. –

İlgili konular