如何设置Ruby套接字上的阻塞操作的超时?
我发现似乎有效的解决方案是使用Timeout :: timeout:
require 'timeout' ... begin timeout(5) do message, client_address = some_socket.recvfrom(1024) end rescue Timeout::Error puts "Timed out!" end
超时对象是一个很好的解决方案.
这是异步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
我认为非阻塞方法是要走的路.
我尝试了上面提到的文章,仍然可以让它挂起来.
这篇文章非阻塞网络和上面的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方法的一个很好的替代品.