2008-10-23 73 views
19

如何設置阻塞在Ruby套接字上的操作的超時時間?如何在Ruby中設置套接字超時?

+2

發現比您接受的更好的解決方案:http://stackoverflow.com/a/12111120/216314 – 2012-09-02 21:28:16

+0

http://ruby-doc.org/stdlib/libdoc/timeout/rdoc/Timeout.html – 2015-10-10 00:17:37

+0

[具有排他鎖的超時模塊](http://stackoverflow.com/a/15304835/1301972)。 – 2015-10-10 00:19:27

回答

17

我找到了解決這似乎工作就是用Timeout::timeout

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

超時對象是一個很好的解決方案。

這是異步的I/O的示例(非阻斷性的並且是異步發生的,以 應用程序的流程。)

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

可用於獲得相同的效果。

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

我認爲非阻塞的方法是要走的路。
我試過上面提到的文章,仍然可以讓它掛起。
這篇文章non blocking networking和jonke的方法讓我走上了正確的道路。我的服務器在初始連接時被阻塞,所以我需要它低一點。
插座的RDoc可以提供更多的細節到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 

得到一個很好的測試。啓動一個簡單的套接字服務器,然後做一個ctrl-z來背景它

IO.select期望數據在10秒內進入輸入流。如果情況並非如此,這可能不起作用。

它應該是TCPSocket開放方法的一個很好的替代品。

相關問題