基本的Ruby TCP服务器演示在启动时失败:`bind':已经在使用的地址,Errno :: EADDRINUSE

时间:2015-11-15 10:11:05

标签: ruby sockets tcp

我将在Ruby中展示一个简单的TCP服务器演示。我的第一个演示是使用经典的C风格的bind-listen-accept-read-write-close方法。这段代码第一次运作良好:

require 'socket'

class Server

  def start(bind: '127.0.0.1', port: nil, backlog: 1)

    Socket.new(:INET, :STREAM).tap do |sock|
      sock.bind Addrinfo.tcp bind, port
      sock.listen backlog

      # the codes of client connecting with it here is for reproducing the issue more easily
      c = Socket.new(:INET, :STREAM)
      c.connect Addrinfo.tcp '127.0.0.1', port

      client, client_addr = sock.accept
      puts "connected from #{client_addr.ip_address}:#{client_addr.ip_port}"

      client.puts "hi"

      client.close
      sock.close

    end
  end

end

Server.new.start(port: 23333)

但是,当我尝试再次运行时,我收到EADDRINUSE错误:

`some-script.rb:8:in `bind': Address already in use - bind(2) for 127.0.0.1:23333 (Errno::EADDRINUSE)`

大约30秒后,我可以再次成功启动脚本。不确定这是否由内核完成。

Dosn't Socket#close是否完全关闭套接字并且内核关闭了TCP连接?

我在Mac OS 10.11.1和Ubuntu 14.04上都尝试过,并得到了相同的结果。 在阅读了ruby的源代码(socket.c)后,我仍然无法弄明白。

有什么建议吗?

1 个答案:

答案 0 :(得分:2)

您可以在致电sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)之前致电sock.bind()来解决此问题。