Ruby Errno :: EADDRINUSE For Simple Socket Example

时间:2016-09-28 04:45:49

标签: ruby sockets

我对使用IO.select的一些套接字代码感到困惑,它在运行后没有清理:

require 'socket'

def run(socket)
  loop do
    begin
      selections, _, _ = IO.select([socket])
      io, _ = selections
      begin
        connection, _ = io.accept
        puts "ACCEPTED: #{connection.inspect}"
      ensure
        puts "CLOSING: #{connection.inspect}"
        connection.close
        puts "CLOSED: #{connection.inspect}"
      end
    rescue Interrupt
      puts "INTERRUPTED"
      break
    end
  end
end

begin
  socket = Socket.new(:INET, :STREAM)
  socket.bind(Socket.pack_sockaddr_in(5000, '0.0.0.0'))
  socket.listen(4)
  puts "LISTENING: #{socket.inspect}"
  run(socket)
ensure
  puts "CLOSING: #{socket.inspect}"
  socket.close
  puts "CLOSED: #{socket.inspect}"
end

运行程序并发送中断信号可以打印:

ruby script.rb 
LISTENING: #<Socket:fd 7>
^CINTERRUPTED
CLOSING: #<Socket:fd 7>
CLOSED: #<Socket:(closed)>

再次运行程序并发出请求:

ruby script.rb 
LISTENING: #<Socket:fd 7>

curl 0.0.0.0:5000

ACCEPTED: #<Socket:fd 8>
CLOSING: #<Socket:fd 8>
CLOSED: #<Socket:(closed)>

curl: empty reply from server

^CINTERRUPTED
CLOSING: #<Socket:fd 7>
CLOSED: #<Socket:(closed)>

尽管调试信息看起来很正常 - 再次快速运行程序会给出:

ruby script.rb
script.rb:25:in `bind': Address already in use - bind(2) for 0.0.0.0:5000 (Errno::EADDRINUSE)
from script.rb:25:in `<main>'

套接字最终会再次绑定(在运行之间有一个长时间的停顿)。有什么不清理?日志使得每个呼叫都被清理干净。

0 个答案:

没有答案