2011-05-31 50 views
1

當.NET 4.0中的HttpWebRequest爲每個請求創建一個套接字連接,但之後無法關閉套接字時,我很難搞清楚。 當我執行例如50個HttpWebRequests時,我在netstat中看到了處於WAIT狀態的50個TCP套接字連接。HttpWebRequest在TIME WAIT中保持套接字

我已有的代碼減少到最低限度:

Dim webReq As HttpWebRequest 
    Dim webRes As HttpWebResponse 
    Dim webStream As IO.StreamReader 
    Dim _answer As String 

    webReq = System.Net.HttpWebRequest.Create(TextBox1.Text) 
    webReq.Timeout = 10000 
    webReq.Method = WebRequestMethods.Http.Get 
    webRes = webReq.GetResponse 

    webStream = New IO.StreamReader(webRes.GetResponseStream(), System.Text.Encoding.ASCII()) 
    _answer = webStream.ReadToEnd 
    RichTextBox1.Text = _answer 

    webRes.Close() 
    webRes = Nothing 
    webReq = Nothing 

任何想法,暗示表示讚賞!

在此先感謝

克里斯

回答

0

你的意思是 'TIME_WAIT'?如果是這樣,請做50個請求,去喝杯咖啡,回到你的盒子,用netstat重新檢查。

關閉TCP套接字將執行終止握手並將套接字對象排隊以釋放。這個套接字實際上並沒有通過TCP設計被釋放幾分鐘 - 即使在成功連接終止之後,一些數據包仍然可能由於慢速路由而中斷&,所以套接字不能被重新分配給另一個連接,直到任何這樣的剩餘物已經死亡。

RGDS, 馬丁

+0

您好Martin,thx爲快速響應。連接在TIME_WAIT中。我在很短的時間內向服務器發佈了很多這些請求。我猜測所有的65536連接都「用完了」。 – Chris 2011-05-31 10:37:04

+0

如果您正在進行壓力測試,則可以更改等待時間。當我測試服務器時,爲了避免所有這些套接字用完,我將它縮短到了6秒。它位於註冊表的某個位置 - 您應該能夠找出Google上的位置。 – 2011-05-31 10:55:43

+0

我能夠通過使用TCP套接字選項來避免TIME_WAIT狀態(如我自己的回答中所述) – Chris 2011-06-14 14:10:04

2

我已經獲得了關於此主題的更深入的瞭解之後,我現在能夠給出一個答案自己。

每當您打開一個套接字並關閉它時,它會在完全關閉之前進入「TIME-WAIT」狀態。這個狀態應該防止後面的tcp連接延遲接收延遲的tcp-packet。 我正在處理向服務器發送數千個CGI請求的應用程序。問題在於使用HTTP/1.0的服務器,這意味着每個請求都會在交換數據後立即打開一個新套接字並關閉它。 經過一段時間後,在「TIME-WAIT」狀態下顯示netstat中的數千個tcp連接。插座,或更精確的端口,變得疲憊不堪。 Windows沒有爲新的CGI請求提供新的套接字。一段時間後,所有TIME-WAIT套接字都關閉,應用程序可以繼續通信。這個問題起源於服務器的HTTP/1.0性質。

從Windows的角度來看,這個問題有兩個「修復」。通過調整註冊表,你可以讓Windows管理更多的默認5000 tcp連接(我讀過一個好的上限可以是20.000)。另一種選擇是減少TIME-WAIT時間本身。這也可以通過調整註冊表來完成。這兩個選項都不是我們的大量套接字耗盡問題的真正解決方案。

在最終的解決方案中,我們使用了一個名爲「SO-LINGER」的TCP套接字選項。在創建端口時設置此選項允許跳過TCP套接字的TIME-WAIT狀態。 請記住,這種狀態存在的原因!跳過它是最後一個選項之一,並且適合我們的需求,因爲我們通過套接字傳輸了幾個字節。在使用此選項之前,請考慮可能的影響。

該項目是在VB .NET 4.0中開發的。我用來創建套接字的代碼如下所示:

Private _plcAddress As String 
Private _plcSocket As Socket 
Private _endPoint As IPEndPoint 

... 

    Dim myOpts As New LingerOption(True, 0) 
    Dim ipAddress As IPAddress = ipAddress.Parse(plcAddress) 

    _plcAddress = plcAddress 
    _plcSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP) 
    _plcSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, myOpts) 
    _endPoint = New IPEndPoint(IPAddress, 80) 
... 
+0

如何在Windows 8.1中增加最大TCP連接數?我也有相同的問題,由於代理失敗 – MonsterMMORPG 2017-03-20 15:31:56

+0

檢查此資源:https://msdn.microsoft.com/en-us/library/aa560610(v=bts.20).aspx可能會有所幫助。最好的問候基督徒 – Chris 2017-03-20 21:08:29