HttpWebRequest的timeout和ReadWriteTimeout(轉載)

公司[1]一牛人看個人代碼,說我設置的timeout有誤,還應該設置ReadWriteTimeout。本人很不服,因而上網查看了相關說明。
HttpWebRequest httpWebRequest = WebRequest.CreateHttp("http://www.kangry.net");
httpWebRequest.ReadWriteTimeout = 300000;
httpWebRequest.Timeout = 100000;

MSDN對ReadWriteTimeout的說明以下:web

在寫入由 GetRequestStream 方法返回的流時,或在讀取由 GetResponseStream 方法返回的流時,會用到 ReadWriteTimeout 屬性。
具體而言,ReadWriteTimeout 屬性控制 Read 方法(用來讀取由 GetResponseStream 方法返回的流)和 Write 方法(用來寫入由 GetRequestStream 方法返回的流)的超時。
若要指定等待請求完成的時間量,請使用 Timeout 屬性[2]。
MSDN對Timeout的說明以下:
Timeout 是進行後續同步請求時使用 GetResponse 方法等待響應以及 GetRequestStream 方法等待流所容許的毫秒數。 Timeout 適用於整個請求和響應,不單獨對GetRequestStream 與 GetResponse 方法調用響應。 若是資源在超時期限內未返回,請求將引起 WebException,並將 Status 屬性設置爲 WebExceptionStatus.Timeout。
Timeout 屬性必須在 GetRequestStream 或 GetResponse 方法被調用以前設置。 在調用 GetRequestStream 或 GetResponse 方法以後更改 Timeout 屬性不起任何做用
Timeout 屬性對使用 BeginGetResponse 或 BeginGetRequestStream 方法生成的異步請求無效[3]。
通俗一點說,Timeout設置的是從發出請求開始算起,到與服務器創建鏈接後收到Http響應頭的時間。ReadWriteTimeout設置的是從創建鏈接開始,到下載數據完畢所歷經的時間。
   
如下一個例子能夠說明這個問題[4]。
首先是抓取的代碼:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://www.kangry.net/Home/t1");
req.Timeout = 5000; //設置超時時間爲5秒

Stopwatch timer = new Stopwatch();
timer.Start();

string data;
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
using (StreamReader reader = new StreamReader(resp.GetResponseStream(), System.Text.Encoding.UTF8))
{
    data = reader.ReadToEnd();
}

timer.Stop();

Console.Write(data + "\r\n" + timer.Elapsed.TotalSeconds.ToString() + "\r\n");

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

其中t1頁面直接返回文本內容,用做基礎對照。
t2頁面設置了一個延時,可是延時時間在超時的範圍內。
t3頁面設置了一個延時,可是延時時間超過抓取程序的timeout時間。
t4頁面首先是先往客戶端發送一部份內容,而後延時一段比timeout更長的時間,模擬出網速很慢的樣子,再把剩下的字符串發送完畢。
代碼以下:服務器

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()
{
    using (var streamWriter = new StreamWriter(Response.Body, System.Text.Encoding.UTF8))
    {
        streamWriter.Write("hello");

        //調用StreamWriter的Flush方法後,Http響應頭和上面的字符串"hello"就會發送給客戶端了
        streamWriter.Flush();

        System.Threading.Thread.Sleep(8000);
        streamWriter.Write("Kangry");
    }

    //若是不使用StreamWriter,也能夠用Response.Body.Write方法來寫入數據到Http響應
    //using (Response.Body)
    //{
    //    byte[] data = System.Text.Encoding.UTF8.GetBytes("hello");
    //    Response.Body.Write(data, 0, data.Length);

    //    //調用Response.Body.Flush方法後,Http響應頭和字符串"hello"就會發送給客戶端了
    //    Response.Body.Flush();

    //    System.Threading.Thread.Sleep(8000);

    //    data = System.Text.Encoding.UTF8.GetBytes("Kangry");
    //    Response.Body.Write(data, 0, data.Length);
    //    Response.Body.Flush();
    //}

    return new EmptyResult();
}

測試的結果是:異步

t1很快返回內容,且沒有錯誤。
t2在3秒後也返回了內容,且沒有錯誤。
t3在5秒後客戶端拋出timeout的錯誤。
t4在8秒後返回內容,並無出現錯誤。
根據測試結果,timeout設置的時間並不包括數據下載所耗費的時間。
MS的牛人果真牛,得多多向他學習!
 

  

 

原文連接學習

相關文章
相關標籤/搜索