最近在項目中要實現一個功能,是關於 Timeout
的,主要是要在要在 TCP 鏈接創建的時間 和 整個請求完成的時間,在這兩個時間層面上,若是超出了設置的時間,就拋出異常,程序中斷。web
研究了一下項目的代碼中,發如今使用HTTP協議,發送請求時,主要用的是微軟的 Microsoft.Net.HttpWebRequest
這個類來發起請求和接收請求的。當時我隱約記得這個類怎麼有點熟悉呀,好像還有 WebRequst
和 HttpClient
這兩個把,還沒開始真正開始去了解Timeout
在HttpWebRequest
中 如何實現的,我先去看了看這三者到底有何不一樣?c#
WebRequest 是 一個抽象類,是HttpWebRequest
的父類。是.NET
中請求和獲取網絡中的數據的一個類。api
HttpWebRequest 是WebReques
t 的一個實現,不只對WebRequest
中的屬性和方法進行了支持,並且還有額外的方法經過Http
協議來和服務端交互。網絡
上面那兩個如今在微軟官方文檔上都不推薦使用了,app
如今所推薦的是 HttpClient
。因爲項目中遺留以前使用的是HttpWebRequest
,因此就在原來的基礎上進行實現,況且的是在HttpClient
中沒有找到TCP
鏈接創建的時間屬性的設定。async
HttpClient 優勢自沒必要多說:性能
雖說性能可能提高了,若是你這樣用,那也是涼涼url
using(HttpClient clinet = new HttpClient()) { var result = await client.GetAsync("http://aspnetmonsters.com"); Console.WriteLine(result.StatusCode); }
用完 Using
後,調用了IDispose
接口。那下次仍是會從新初始化.net
這樣使用就沒問題了code
private static HttpClient Client = new HttpClient();
也多是我英文的理解能力有點差,在開始我就注意到這個類裏面的這兩個屬性,可是我如何也沒法和 TCP 創建前所用的鏈接時間 與 請求完成的時間聯繫起來。微軟官方文檔解釋以下:
Timeout:
Timeout is the number of milliseconds that a subsequent synchronous request made with the GetResponse method waits for a response, and the GetRequestStream method waits for a stream. The Timeout applies to the entire request and response, not individually to the GetRequestStream and GetResponse method calls. If the resource is not returned within the time-out period, the request throws a WebException with the Status property set to WebExceptionStatus.Timeout.
The Timeout property has no effect on asynchronous requests made with the BeginGetResponse or BeginGetRequestStream method.
ReadWriteTimeout:
The ReadWriteTimeout property is used when writing to the stream returned by the GetRequestStream method or reading from the stream returned by the GetResponseStream method.
Specifically, the ReadWriteTimeout property controls the time-out for the Read method, which is used to read the stream returned by the GetResponseStream method, and for the Write method, which is used to write to the stream returned by the GetRequestStream method.
設置實際上是很方便的,以下所示:
HttpWebRequest request = (HttpWebRequest)WebRequest.Creat("<your url>"); //Set timeout to 1s request.Timeout = 1000; //Set ReadWriteTimeout to 3000 request.ReadWriteTimeout = 3000; HttpWebResponse response = (HttpWebResponse)request.GetResponse();
最後在捕捉異常的時候,發現了一個很奇怪的地方,就是使用兩段代碼,卻拋出了不一樣的異常,
第一段代碼:
HttpWebRequest request = (HttpWebRequest) WebRequest.Create("https://www.alibabacloud.com"); request.Timeout = 5000; HttpWebResponse response = (HttpWebResponse) request.GetResponse(); HttpWebRequest request2 = (HttpWebRequest) WebRequest.Create("https://www.cnblogs.com"); request2.Timeout = 1; HttpWebResponse response2 = (HttpWebResponse) request2.GetResponse(); //Exception /* Unhandled Exception: System.Net.WebException: The operation has timed out. at System.Net.HttpWebRequest.GetResponse() */
第二段
HttpWebRequest request = (HttpWebRequest) WebRequest.Create("https://www.alibabacloud.com"); request.Timeout = 5000; HttpWebResponse response = (HttpWebResponse) request.GetResponse(); request = (HttpWebRequest) WebRequest.Create("https://www.cnblogs.com"); request.Timeout = 1; response = (HttpWebResponse) request.GetResponse(); //Exception /* Unhandled Exception: System.OperationCanceledException: The operation was canceled. at System.Net.HttpWebRequest.GetResponse() */
初步估計的緣由是,Http 請求中 Keep-Alive的關係,還有一個多是 Timeout 的這個說明:
The Timeout applies to the entire request and response, not individually to the GetRequestStream and GetResponse method calls. 然而具體的還沒搞清楚,還須要去驗證。
其實,設置這兩個屬性你可能只須要找到文檔,分分鐘就能夠搞定,可是我爲何會在這個過程遇到這些問題呢?一方面是對於C# 中網絡請求的不熟悉,其次是找個時間,把之前的代碼須要重構一下了,好比把HttpWebRequest
換成 HttpClient
等等。也讓我加深了對Http協議
的理解。