WebRequest 逾時不起作用

來源:互聯網
上載者:User
 //WebRequest request = WebRequest.Create(uri);                HttpWebRequest  request = (HttpWebRequest)HttpWebRequest.Create(uri);                //request.Timeout = Timeout.Infinite;                request.Timeout = 20000;                //request.AllowAutoRedirect = true;                //request.AllowWriteStreamBuffering = true;                //request.Referer = "";                response = request.GetResponse();

轉載自:http://blog.sina.com.cn/s/blog_6fe1bc2e0101emc5.html

【問題】

用C#類比網頁登陸,其中去請求幾個頁面,會發起對應的http的請求request,其中keepAlive設定為true,提交請求後,然後會有對應的response:

resp = (HttpWebResponse)req.GetResponse();

之前的多次調試,一直都是可以正常獲得對應的response,然後讀取html頁面的。

但是後來幾次的調試,在沒有改變代碼的前提下,結果GetResponse卻始終會逾時死掉。

 

【解決過程】

1.預設request的timeout是1000000毫秒=100秒,都會逾時,手動改為10秒,因此就更容易逾時了,無法解決問題。

2.將http的request的keepAlive設定為false,問題依舊。

3.去參考:c# request.GetResponse();逾時問題的解決,和HttpWebRequest多線程效能問題,請求逾時的錯誤,

去把前面共4次的httprequest,每次都增加對應的:

resp = null;
。。。
if (resp != null)
{
   
resp.Close();
}
if (req != null)
{
   
req.Abort();
}

結果還是沒解決問題。

4. 同樣參考:HttpWebRequest多線程效能問題,請求逾時的錯誤,

去嘗試關於DefaultConnectionLimit的設定,改為為10:

System.Net.ServicePointManager.DefaultConnectionLimit = 10;

問題依舊。

5.又去測試了下,關於response.Close()

也是沒解決問題。

6. 最後無意間,索性不抱希望的,再次DefaultConnectionLimit設定為更大的值50:

System.Net.ServicePointManager.DefaultConnectionLimit = 50;

試了試,結果就解決逾時的問題了。

然後才搞懂原因。

之前預設設定為2,後來改為10,都沒有解決問題的原因在於,當前有很多個http的串連,沒有被關閉掉,

而這些keepalive的串連,都是

由於代碼中,對於前面多個request。其都是keepalive為true,以及多個response也沒有close,

而之前調試了很多次了,所以,此時已經存在了很多個alive的http串連了,已經超過了10個了,所以前面設定了DefaultConnectionLimit
為10,也還是沒用的。

而改為50,才夠用。

【總結】

此處GetResponse超過的原因是,當前存在太多數目的alive的http串連(大於10個),所以再次提交同樣的http的request,再去GetResponse,就會逾時死掉。

解決辦法就是,把DefaultConnectionLimit
設定為一個比較大一點的數值,此數值保證大於你當前已經存在的alive的http串連數即可。

【經驗總結】

以後寫http的request代碼,如果不是必須的要keepalive的,那麼就要設定KeepAlive為false:

req.KeepAlive = false;

以及做對應的收尾動作:

if (resp != null)
{
   
resp.Close();
}
if (req != null)
{
   
req.Abort();
}

 

【後記 2012-03-01】

又偶爾遇到一次,DefaultConnectionLimit已經是200了,足夠大了,但是GetResponse和GetRequestStream,還是會逾時死掉的問題,具體是什麼原因導致的還不是很清楚,但是經過折騰,參考:

HttpWebResponse’s GetResponse() hangs and
timeouts

在:

req = (HttpWebRequest)WebRequest.Create(constSkydriveUrl);
setCommonHttpReqPara(ref req);
resp = (HttpWebResponse)req.GetResponse();

之前,添加一句記憶體回收:

System.GC.Collect();

然後就解決了GetResponse的逾時問題,並且後面的GetRequestStream也同時可以正常工作,不逾時了。

所以,看起來像是當前系統由於調試多次,並且HttpWebRequest和HttpWebResponse都是沒有正常去Close的,可能會殘留一些
http的連結,然後就可能影響到了後續對於http的使用,記憶體回收後,估計就把殘餘的http相關資源釋放了,然後http就可以正常工作了。

 

【總結】

對於GetResponse或GetRequestStream逾時死掉的原因,可能是:

1.DefaultConnectionLimit是預設的2,而當前的Http的connection用完了,導致後續的GetResponse或GetRequestStream逾時死掉

==>>
預設系統只支援同時存在2個http的connection

==>>
使用HttpWebRequest之後如果沒有close,則會佔用1個http的connection,所以如果超過2次使用
HttpWebRequest而沒有close,那麼就用完系統的http的connection,之後再去使用
HttpWebRequest,GetResponse就會死掉

解決辦法:

辦法1:

每次使用完HttpWebRequest,使用


?
12 req.Close();req=null;

去關閉對應的http connection

最好對應的HttpWebResponse也要close:


?
12 resp.Close();resp = null;

方法2:

修改DefaultConnectionLimit的值,改為足夠大,比如:


?
1 System.Net.ServicePointManager.DefaultConnectionLimit =
200;

 

2.系統中Http相關的資源沒有正確釋放,導致後續GetResponse或GetRequestStream逾時死掉

就像我此處遇到的,可能是之前調用http相關函數,沒有正確完全釋放資源,導致雖然DefaultConnectionLimit給了足夠大,但是還是
會死掉,此時在http請求代碼之前去做一次記憶體回收,則後續http的GetResponse或GetRequestStream就正常了,就不會逾時
死掉了。

參考代碼如下:


?
12345 System.GC.Collect();  req =
(HttpWebRequest)WebRequest.Create(constSkydriveUrl);
setCommonHttpReqPara(ref
req);resp = (HttpWebResponse)req.GetResponse();

 

3.Http的GET請求時,不要手動設定ContentLength的值

這個是參考這裡:HttpWebRequest.GetResponse()
hangs the second time it is called而記錄於此的,也許有人是此原因,所以可供參考一下。

即Http的GET請求,不要添加類似如下的代碼:


?
12 if (m_contentLength >
0)
    httpWebRequest.ContentLength
= m_contentLength;

不要去手動修改對應的ContentLength的值,C#的http相關庫函數,會自動幫你計算的。

註:POST方法中,的確是要手動填充資料和算出資料大小,然後手動給ContentLength賦值的。

 

4.其他可能的一些原因

(1)關於KeepAlive的問題

如果Http的請求,是設定了KeepAlive=true的話,那麼對應的http的connection會和伺服器保持串連的。

所以如果上述辦法都不能解決逾時的問題,可以嘗試將keepAlive設定為false試試,看看能否解決。

(2)關於Sleep

有些人好像是通過在http請求前,加了對應的Sleep,結果解決了此問題。需要的人,也可以試試。

(3)HttpWebRequest的Timeout

一般來說,既然逾時了,往往是由於錯誤使用函數或者網路有問題導致的,所以實際上此處對於有些人去把HttpWebRequest的Timeout的值改的更大,往往都是沒用的。

只不過,萬一是由於網路響應慢而導致逾時,那麼倒是可以嘗試,將HttpWebRequest的Timeout的值改為更大。

(其中HttpWebRequest的Timeout預設的值是100,000 milliseconds ==100
seconds)

參考代碼:


?
1 req.Timeout = 5 * 60 * 1000; // 5
minutes

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.