2017-05-08 24 views
0

我有一個系統,其中在後臺運行的服務器進程由控制程序控制。LINUX上的TIME_WAIT和EADDRINUSE

控制程序是一個簡單的腳本,執行一個命令然後退出。對於運行命令,它創建一個新的服務器進程;對於其他人(包括關機),它通過保留的控制端口將命令發送到服務器。

控制程序創建一個套接字,連接到服務器的控制端口,發送一個數據字符(一個命令),從套接字讀取回復,關閉套接字,顯示回覆給用戶並退出。服務器接受控制套接字上的連接,讀取數據字符,發送回覆,關閉子套接字並繼續收聽。當服務器關閉時,它也會關閉父級控制套接字。

這一直工作在Windows XP/Python的2.6.6數年。最近我們嘗試移植到Linux(Ubuntu 16.04.2 GNU/Linux 4.4.0-62-generic x86_64/Python 2.7.12),但是那裏有重新啓動命令(立即關閉緊跟着運行)失敗:當新的服務器進程嘗試要將控制套接字綁定到控制端口,它將獲得EADDRINUSE。

從netstat的輸出顯示,用於關斷命令的連接保持在TIME_WAIT狀態,並且繼續如此大約兩分鐘。

我已閱讀了有關此主題的以前的帖子。我曾嘗試在服務器的控制套接字上設置SO_REUSEADDR和/或SO_REUSEPORT。我試圖增強服務器和控制程序之間的協議,以確保控制程序首先關閉其連接側,但到目前爲止,我還沒有找到可行的組合。我想知道是否有任何解決方案。

由於在同一臺機器上運行的服務器和控制程序,連接兩側的細節將在操作系統的狀態表,以及一個或其它必須在TIME_WAIT留下。

是否爲控制程序的入口阻止服務器綁定到端口?

我注意到,在Windows上還連接在TIME_WAIT狀態下離開,但在Windows並不妨礙新的服務器進程捆綁到同一個控制端口。

+0

嗨,歡迎來到StackOverflow!您可能想編輯您的問題以包含一些格式。現在,它很難閱讀! –

回答

0

我已經回答了我自己的問題。爲了獲得所需的行爲,我需要在服務器的控制套接字(僅)上設置SO_REUSEADDR(僅)。沒有必要使用SO_REUSEPORT。沒有必要對控制程序做任何事情。首先關閉連接是沒有區別的。

我第一次嘗試沒有成功,因爲我犯了一個愚蠢的錯誤。 (我使用了錯誤的變量。)