如何设置Ruby套接字上阻塞操作的超时?
答案 0 :(得分:17)
我发现似乎有用的解决方案是使用Timeout::timeout:
require 'timeout'
...
begin
timeout(5) do
message, client_address = some_socket.recvfrom(1024)
end
rescue Timeout::Error
puts "Timed out!"
end
答案 1 :(得分: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
答案 2 :(得分:8)
我认为非阻塞方法是可行的方法
我尝试了上面提到的文章,仍然可以让它挂起。
这篇文章non blocking networking以及jonke的上述方法让我走上了正确的道路。我的服务器在初始连接时阻塞,所以我需要它稍微低一点
socket 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的open方法的一个很好的替代品。