我试图通过 SO_RCVTIMEO 套接字选项在 Ruby 中设置套接字超时,但它似乎对任何最近的 *nix 操作系统都没有影响。
使用 Ruby 的 Timeout 模块不是一个选择,因为它需要为每个超时生成和连接线程,这可能会变得昂贵。在需要低套接字超时且具有大量线程的应用程序中,它本质上会降低性能。许多地方都注意到了这一点,包括堆栈溢出 https://stackoverflow.com/questions/231647/how-do-i-set-the-socket-timeout-in-ruby.
我读过 Mike Perham 关于这个主题的优秀文章here http://www.mikeperham.com/2009/03/15/socket-timeouts-in-ruby/为了将问题减少到一个可运行代码文件,创建了一个简单的 TCP 服务器示例,该服务器将接收请求,等待请求中发送的时间,然后关闭连接。
客户端创建一个socket,设置接收超时时间为1秒,然后连接到服务器。客户端告诉服务器在 5 秒后关闭会话,然后等待数据。
客户端应在一秒后超时,但在 5 秒后成功关闭连接。
#!/usr/bin/env ruby
require 'socket'
def timeout
sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
# Timeout set to 1 second
timeval = [1, 0].pack("l_2")
sock.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, timeval
# Connect and tell the server to wait 5 seconds
sock.connect(Socket.pack_sockaddr_in(1234, '127.0.0.1'))
sock.write("5\n")
# Wait for data to be sent back
begin
result = sock.recvfrom(1024)
puts "session closed"
rescue Errno::EAGAIN
puts "timed out!"
end
end
Thread.new do
server = TCPServer.new(nil, 1234)
while (session = server.accept)
request = session.gets
sleep request.to_i
session.close
end
end
timeout
我也尝试过使用 TCPSocket (自动连接)做同样的事情,并且在redis https://github.com/ezmobius/redis-rb/blob/c41bc94ea6e6eebb718428d74d22c84b6d2513a4/lib/redis/connection/ruby.rb#L44-55和其他项目。
此外,我可以通过调用来验证该选项是否已设置getsockopt
像这样:
sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO).inspect
设置此套接字选项实际上对任何人都有效吗?