webrequest的timeout屬性做用範圍

使用c#進行抓取網頁信息時,使用httpwebrequest進行抓取,一般都會自定義設置一個timeout超時值,若是不設置的話,系統默認的超時值比較高,每每長時間的等待沒有意義,不如手動設置一個比較小的值,例如5秒,這樣5秒內如若還連不上,則能夠考慮從新創建鏈接或者作其餘事情。web

不過使用中發現一個奇怪的現象,就是對一個頁面的抓取,已經超過了設置的timeout值了,既沒有拋出異常也沒有完成數據抓取,仍須要等待很是長的時間後才報告一個錯誤。仔細查看了關於 HttpWebRequest.Timeout 的解釋:c#

Timeout 是進行後續同步請求時使用 GetResponse 方法等待響應以及 GetRequestStream 方法等待流所容許的毫秒數。 Timeout 適用於整個請求和響應,不單獨對 GetRequestStream 與 GetResponse 方法調用響應。 若是資源在超時期限內未返回,請求將引起 WebException,並將 Status 屬性設置爲 WebExceptionStatus.Timeout。
Timeout 屬性必須在 GetRequestStream 或 GetResponse 方法被調用以前設置。 在調用 GetRequestStream 或 GetResponse 方法以後更改 Timeout 屬性不起任何做用
Timeout 屬性對使用 BeginGetResponse 或 BeginGetRequestStream 方法生成的異步請求無效。服務器


以爲timeout的做用域是控制與目標服務器創建鏈接的超時時間,也就是說,當咱們和服務器能在規定的timeout時間內創建tcp鏈接,便不會異常,然後,頁面數據的下載很慢的過程不在timeout的範圍內。這就致使了該下載過程漫長而無果。爲了驗證這個猜測,我作了幾個頁面,分別在裏面設置System.Threading.Thread.Sleep(n)方法來人爲延時。mvc

首先是抓取的代碼:asp.net

HttpWebRequest req =(HttpWebRequest)  WebRequest.Create("http://lixin.me/t1");
            req.Timeout = 5000; //設置超時時間爲5秒
            Stopwatch timer = new Stopwatch();
            timer.Start();
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            StreamReader reader = new StreamReader(resp.GetResponseStream());
            string data = reader.ReadToEnd();
            timer.Stop();
            textBox1.AppendText(data + "\r\n"+timer.Elapsed.TotalSeconds.ToString()+"\r\n");


其中我作了幾個頁面,分別是」t1″、「t2」、「t3」、「t4」。異步

其中t1頁面直接返回文本內容,用做基礎對照。tcp

t2頁面設置了一個延時,可是延時時間在超時的範圍內。測試

t3頁面設置了一個延時,可是延時時間超過抓取程序的timeout時間。spa

t4頁面首先是先往客戶端發送一部份內容,而後延時一段比timeout更長的時間,模擬出網速很慢的樣子,再把剩下的字符串發送完畢。.net

代碼以下:

public ActionResult t1()
        {
            return Content("直接返回內容。");
        }
        public ActionResult t2()
        {
            System.Threading.Thread.Sleep(3000);
            return Content("休息了3秒");
        }
        public ActionResult t3()
        {
            System.Threading.Thread.Sleep(7000);
            return Content("休息了7秒");
        }
        public ActionResult t4()
        {
            //這個是僞代碼,實際使用的是 t4.aspx 寫的,不是asp.net mvc
            Response.Write("hello");
            Response.Flush();
            System.Threading.Thread.Sleep(8000);
            return Content(" lixin");
        }

測試的結果是:

t1很快返回內容,且沒有錯誤。

t2在3秒後也返回了內容,且沒有錯誤。

t3在5秒後客戶端拋出timeout的錯誤。

t4在8秒後返回內容,並無出現錯誤。

根據測試結果,timeout設置的時間並不包括數據下載所耗費的時間。

那麼要在規定的時間內完成下載數據任務不然就從新開始呢?這就得使用HttpwebRequest另外一個屬性值了:ReadWriteTimeout

在寫入由 GetRequestStream 方法返回的流時,或在讀取由 GetResponseStream 方法返回的流時,會用到 ReadWriteTimeout 屬性。
具體而言,ReadWriteTimeout 屬性控制 Read 方法(用來讀取由 GetResponseStream 方法返回的流)和 Write 方法(用來寫入由 GetRequestStream 方法返回的流)的超時。
若要指定等待請求完成的時間量,請使用 Timeout 屬性。

根據文檔描述,這個屬性的設置就是設置讀取數據流的超時時間了。

相關文章
相關標籤/搜索