我试图通过 SO_RCVTIMEO 套接字选项使 Ruby 中的套接字超时,但它似乎对任何最近的 *nix 操作系统都没有影响。
使用 Ruby 的 Timeout 模块不是一个选项,因为它需要为每个超时生成和加入线程,这可能会变得很昂贵。在需要低套接字超时且具有大量线程的应用程序中,它基本上会降低性能。这在包括Stack Overflow在内的许多地方都已注意到。
我在这里阅读了 Mike Perham 关于该主题的出色文章,为了将问题减少到一个可运行代码文件,我创建了一个 TCP 服务器的简单示例,它将接收请求,等待请求中发送的时间量和然后关闭连接。
客户端创建一个套接字,设置接收超时为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和其他项目中看到了类似的代码。
此外,我可以通过如下调用来验证该选项是否已设置getsockopt
:
sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO).inspect
设置此套接字选项实际上对任何人都有效吗?