目標機器主動拒絕連線導致無法建立連線
P粉268654873
2023-08-20 12:40:57
<p>有時在我進行HttpWebRequest到一個Web服務時,會出現以下錯誤。我也在下面複製了我的程式碼。 </p>
<hr />
<pre>System.Net.WebException: 無法連線到遠端伺服器 ---> System.Net.Sockets.SocketException: 由於目標電腦積極拒絕,無法建立連線 127.0.0.1:80
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Intception time);
--- 內部異常堆疊追蹤的結尾 ---
at System.Net.HttpWebRequest.GetRequestStream()
</pre>
<hr />
<pre class="brush:php;toolbar:false;">ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.PreAuthenticate = true;
request.Credentials = networkCredential(sla);
request.Method = WebRequestMethods.Http.Post;
request.ContentType = "application/x-www-form-urlencoded";
request.Timeout = v_Timeout * 1000;
if (url.IndexOf("asmx") > 0 && parStartIndex > 0)
{
AppHelper.Logger.Append("#############" sla.ServiceName);
using (StreamWriter reqWriter = new StreamWriter(request.GetRequestStream()))
{
while (true)
{
int index01 = parList.Length;
int index02 = parList.IndexOf("=");
if (parList.IndexOf("&") > 0)
index01 = parList.IndexOf("&");
string parName = parList.Substring(0, index02);
string parValue = parList.Substring(index02 1, index01 - index02 - 1);
reqWriter.Write("{0}={1}", HttpUtility.UrlEncode(parName), HttpUtility.UrlEncode(parValue));
if (index01 == parList.Length)
break;
reqWriter.Write("&");
parList = parList.Substring(index01 1);
}
}
}
else
{
request.ContentLength = 0;
}
response = (HttpWebResponse)request.GetResponse();</pre>
<p><br /></p>
如果這種情況總是發生,那麼這實際上意味著機器存在,但指定連接埠上沒有服務在監聽,或有防火牆阻止你。
如果這種情況偶爾發生 - 你使用了"有時"這個詞 - 並且重試成功,那很可能是因為伺服器的'backlog'已滿。
當你等待在一個監聽套接字上被接受時,你會被放置在一個backlog中。這個backlog是有限的,非常短 - 值為1、2或3並不罕見 - 所以作業系統可能無法將你的請求排隊等待'accept'來消費。
backlog是
listen
函數的一個參數 - 所有的語言和平台在這方面基本上都有相同的API,甚至包括C#。如果你控制伺服器,這個參數通常是可設定的,並且可能從某個設定檔或註冊表中讀取。請了解如何配置你的伺服器。如果你編寫了伺服器,你可能在套接字的接受過程中有很重的處理,這可以更好地移動到一個單獨的工作線程中,這樣你的接受總是準備好接收連接。你可以探索各種架構選擇來減輕客戶端的排隊和順序處理。
無論如何,無論你是否可以增加伺服器的backlog,你的客戶端程式碼都需要重試邏輯來處理這個問題- 因為即使有一個很長的backlog,伺服器在那個時間可能仍然會接收到很多其他連接埠的請求。
有一種罕見的可能性是,如果NAT路由器的映射連接埠耗盡,會出現此錯誤。不過我認為這種可能性太小了,因為路由器在耗盡之前可以同時建立64K個到相同目標位址/連接埠的連線。