2015-11-15 20 views
2

我在Ruby中提出了一個簡單的TCP服務器演示。我的第一個演示是使用經典的C風格的bind-listen-accept-read-write-close方法。此代碼工作得很好,第一次:啓動時基本Ruby TCP服務器演示失敗:`bind':地址已在使用中,Errno :: EADDRINUSE

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完全關閉socket和內核關閉TCP連接?

我在Mac OS 10.11.1和Ubuntu 14.04上都試過了,得到了同樣的結果。 閱讀ruby的源代碼(socket.c)後,我仍然無法弄清楚。

有什麼建議嗎?

回答

2

您可以在致電sock.bind()之前致電sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)解決此問題。

+0

謝謝@keithmo,重複使用作品。 – qhwa

相關問題