[英]Winsock tcp/ip Socket listening but connection refused, race condition?
這涉及兩個自動化的單元測試,每個單元測試都啟動一個tcp / ip服務器,該服務器創建一個無阻塞套接字,然后在select()上的循環中為連接並下載一些數據的客戶端綁定()和listen()s。
問題是它們在單獨運行時可以完美工作,但是當作為測試套件運行時,第二個測試客戶端將無法與WSACONNREFUSED連接...
除非
它們之間有幾秒鍾的Thread.Sleep()?
有趣的是,每1秒就會有一個重試循環,以便在發生任何故障后進行連接。 因此,第二個測試會循環一段時間,直到10分鍾后超時。
在這段時間內,netstat -na顯示服務器套接字處於LISTEN狀態的正確端口號。 那么,它是否處於偵聽狀態? 為什么不接受連接?
在代碼中,有一些日志消息顯示select NEVER甚至沒有准備好讀取套接字(這意味着在將其應用於偵聽套接字時准備接受連接)。
顯然,該問題必須與完成一個測試(即在套接字的每一端上的close()和shutdown())與啟動下一個測試之間的某些競爭條件有關。
如果重試邏輯允許其在幾秒鍾后最終連接,這並不會太糟糕。 但是,它似乎“塞滿了”,甚至不會重試。
但是,出於某種奇怪的原因,即使通過不斷拒絕連接,偵聽套接字也說它處於LISTEN狀態。
因此,這意味着實際上是Windoze O / S在捕獲SYN數據包並返回RST數據包(這意味着“連接被拒絕”)。
我唯一一次看到此錯誤的時間是代碼中的問題導致數百個套接字陷入TIME_WAIT狀態。 但事實並非如此。 netstat在任何給定時刻僅顯示十幾個套接字,TIME_WAIT中只有1或2個套接字。
請幫忙。
我在具有各種內核數量的各種Windows操作系統(XP到Windows 7)的構建機器上運行了許多這樣的測試,但我從未見過這是一個問題。
我不認為將偵聽套接字轉換為TIME_WAIT
可能是您的問題; 我當然從未見過它,我會定期在TIME_WAIT
延遲時間內使用與啟動和停止服務器相同的端口運行客戶端服務器測試。
如果您在第一個服務器關閉其套接字之前啟動了第二個服務器(或者,如果套接字在TIME_WAIT
),那么我希望第二個服務器在嘗試bind()
時出錯。
我個人認為,您的代碼中有一個問題可能是接受連接-這是您的測試可能發現了一個錯誤;)
我們可以看看您的監聽和接受循環之間的代碼嗎?
如果您顛倒測試順序,您是否有問題?
客戶端和服務器是否在同一台計算機上運行,如果不是,客戶端和服務器是否會發生變化?
等等。
我有一些TCP測試工具http://www.lenholgate.com/blog/2005/11/windows-tcpip-server-performance.html ,如果您將測試系統設置為通過該鏈接針對示例運行測試客戶端從這一個服務器http://www.lenholgate.com/blog/2005/11/simple-echo-servers.html仍然看到問題嗎? (也就是說,在您的測試系統中將服務器與客戶端一起運行,以使其與運行您的東西相同,並且我的東西可以工作嗎?)。
然后,根本的問題是關閉套接字,線程正在嘗試讀取任何剩余的字節。 這是作為一個單獨的線程完成的,該線程將套接字的讀取端保持打開狀態固定的毫秒數,同時嘗試重復讀取任何數據。
該邏輯已被替換,可以更智能地讀取任何數據並在讀取返回0時正確關閉。因此,關閉速度更快。
因此,事實證明我自己的代碼沒有正確關閉套接字。
感謝您的所有幫助!
從此MSDN網站 :
TIME_WAIT狀態確定TCP釋放封閉的連接並重用其資源之前必須經過的時間。 關閉和釋放之間的時間間隔稱為TIME_WAIT狀態或2MSL狀態。 在此期間,與建立新連接相比,可以以更少的成本為客戶端和服務器重新打開連接。 TIME_WAIT行為是在RFC 793中指定的,該行為要求TCP保持關閉連接的時間間隔至少等於網絡最大段生存時間(MSL)的兩倍。 釋放連接時,其套接字對和用於該套接字的內部資源可用於支持另一個連接。
關閉連接后,Windows TCP會恢復為TIME_WAIT狀態。 處於TIME_WAIT狀態時,無法重復使用套接字對。 可以通過修改以下表示TIME_WAIT周期(以秒為單位)的DWORD注冊表設置來配置TIME_WAIT周期。
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters\TcpTimedWaitDelay
默認情況下,MSL定義為120秒。 TcpTimedWaitDelay注冊表設置的默認值為240秒,是最大段生存時間120秒或4分鍾的2倍。 但是,您可以使用此條目來自定義間隔。 減少該條目的值可使TCP更快地釋放關閉的連接,從而為新的連接提供更多的資源。 但是,如果該值太低,TCP可能會在連接完成之前釋放連接資源,從而要求服務器使用其他資源來重新建立連接。 此注冊表設置可以設置為0到300秒。
我認為您可以將值設置為30的最小值(嘗試較小,但可能不起作用)
您可以查看Winsock程序員的FAQ,以獲得更詳細的解釋。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.