我试图通过SO_RCVTIMEO套接字选项在Ruby中使套接字超时,但它似乎对任何最近的*nix操作系统没有影响.
使用Ruby的Timeout模块不是一个选项,因为它需要为每个超时生成并加入线程,这可能会变得很昂贵.在需要低套接字超时且具有大量线程的应用程序中,它基本上会导致性能下降.许多地方都已经注意到这一点,包括Stack Overflow.
我读过迈克·佩勒姆对这个问题的优秀岗位在这里,并在努力把问题缩小到可运行代码的一个文件中创建一个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) …Run Code Online (Sandbox Code Playgroud) 为什么在单独尝试锁定文件时,Ruby的File#flock不能按预期工作?锁定块中的文件不是解决此问题的正确方法,因为重点是显示锁定持久锁的行为.在块中使用File#flock会在块退出时释放锁定,因此它不能正确显示问题.
File#flock以各种方式失败,尤其是在请求非阻塞锁定时.一些例子如下.
使用多个独占锁时无限等待,因为#flock不提供超时锁定请求的方法.
# First lock succeeds.
f1 = File.open('foo', File::RDWR|File::CREAT, 0644)
f1.flock(File::LOCK_EX)
# => 0
# This never returns.
f2 = File.open('foo', File::RDWR|File::CREAT, 0644)
f2.flock(File::LOCK_EX)
Run Code Online (Sandbox Code Playgroud)在文件被独占锁定时请求非阻塞锁定会导致无效的参数异常.
f1 = File.open('foo', File::RDWR|File::CREAT, 0644)
f1.flock(File::LOCK_EX)
# => 0
f2 = File.open('foo', File::RDWR|File::CREAT, 0644)
f2.flock(File::LOCK_NB)
# => Errno::EINVAL: Invalid argument - foo
Run Code Online (Sandbox Code Playgroud)文档说#flock"根据locking_constant(逻辑或下表中的值)锁定或解锁文件." 但是,Logical OR会提升Errno::EINVAL或Errno::EBADF取决于平台.
f1 = File.open('foo', File::RDWR|File::CREAT, 0644)
f1.flock(File::LOCK_EX)
# => 0
f2 = File.open('foo', File::RDWR|File::CREAT, 0644)
f2.flock(File::LOCK_NB || File::LOCK_EX)
# …Run Code Online (Sandbox Code Playgroud)