基本的Ruby TCP服务器演示在启动时失败:`bind’:已经在使用的地址,Errno :: EADDRINUSE
我在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
#close完全关闭socket和内核关闭TCP连接?
我在Mac OS 10.11.1和Ubuntu 14.04上都尝试了它,并得到了相同的结果。 在阅读了ruby的源代码(socket.c)后,我仍然无法弄明白。
任何建议?
您可以在调用sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
之前调用sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
来sock.bind()
。