WebRequest類和WebResponse類

WebRequest類和WebResponse類

WebClient類使用起來比較簡單,但是它的功能非常有限,特別是不能使用它提供身份驗證證書。這樣,在上傳數據時問題就出現了,許多站點都不會接受沒有身份驗證的上傳文件。儘管可以給請求添加標題信息並檢查響應中的標題信息,但這僅限於一般意義上的檢查,對於任何一個協議,WebClient沒有具體的支持。由於WebClient是通用的類,主要用於處理髮送請求和接收響應的協議(例如HTTP、FTP等)。它不能處理任一協議的任何附加特性,例如專用於HTTP的cookie。如果想利用這些特性,就需要使用System.Net命名空間中以WebRequest類和WebResponse類爲基類的一系列類。

首先討論怎樣使用這些類下載Web頁——這個示例與前面的示例一樣,但使用WebRequest類和WebResponse類。在此過程中,將解釋涉及到的類的層次結構,然後闡述怎樣利用這個層次所支持的其他HTTP特性。

下面的代碼是在BasicWebClient示例的基礎上修改而成的,目的是讓它使用WebRequest類和WebResponse類。

public Form1()

{

   InitializeComponent();

 

   WebRequest wrq = WebRequest.Create("http://www.wrox.com");

   WebResponse wrs = wrq.GetResponse();

   Stream strm = wrs.GetResponseStream();

   StreamReader sr = new StreamReader(strm);

   string line;

   while ( (line = sr.ReadLine()) != null)

   {

      listBox1.Items.Add(line);

   }

   strm.Close();

}

在這段代碼中,首先對代表Web請求的對象進行實例化。但在此並不是使用構造函數來實例化對象,而是調用靜態的WebRequest.Create()方法,在下一小節中將解釋這樣做的原因。WebRequest類是支持不同網絡協議的類層次結構的一部分,爲了給請求類型接收一個對正確對象的引用,需要一個工廠(factory)機制。WebRequest.Create()方法會爲給定的協議創建合適的  對象。

WebRequest類代表要給某個URI發送信息的請求,URI作爲參數傳送給Create()方法。WebResponse類代表從服務器獲取的數據。調用WebRequest.GetResponse()方法,實際上是把請求發送給Web服務器,創建一個Response對象,檢查返回的數據。與WebClient對象一樣,可以得到一個代表數據的數據流,但是,這裏的數據流是使用WebResponse.GetResponseStream()方法獲得的。

下面將討論WebRequest和WebResponse的其他特性。我們將會看到WebRequest和WebResponse和其他相關的類提供的良好支持。
1.  HTTP標題信息

HTTP協議的一個重要方面就是能夠利用請求和響應數據流發送擴展的標題信息。標題信息可以包括cookies、以及發送請求的特定瀏覽器(用戶代理)的一些詳細信息。.NET Framework爲訪問最重要的數據提供了支持。WebRequest類和WebResponse類提供了讀取標題信息的一些支持。而兩個派生的類HttpWebRequest類和HttpWebResponse類提供了其他HTTP特定的信息。如後面所述,用HTTP URI創建WebRequest會生成一個HttpWebRequest對象實例。因爲HttpWebRequest派生自WebRequest,可以在需要WebRequest的任何地方使用新實例。另外,還可以把實例的類型強制轉換爲HttpWebRequest引用,訪問HTTP協議特定的屬性。同樣,在使用HTTP時,GetResponse()方法調用會把HttpWebResponse實例返回爲HttpWebResponse引用,也可以進行一個簡單的強制轉換,以訪問HTTP特定的特性。

可以在GetResponse()方法調用之前添加如下代碼,檢查兩個標題屬性:

WebRequest wrq = WebRequest.Create("http://www.wrox.com");

HttpWebRequest hwrq = (HttpWebRequest)wrq;

 

listBox1.Items.Add("Request Timeout (ms) = " + wrq.Timeout);

listBox1.Items.Add("Request Keep Alive = " + hwrq.KeepAlive);

listBox1.Items.Add("Request AllowAutoRedirect = " + hwrq.AllowAutoRedirect);

Timeout屬性的單位是毫秒,其默認值是100 000。可以設置這個屬性,以控制WebRequest對象在產生WebException之前要在響應中等待多長時間。可以檢查屬性WebException.Status,看看產生異常的原因。這個枚舉類型包括超時的狀態碼、連接失敗、協議錯誤等。

KeepAlive屬性是對HTTP協議的特定擴展,所以可以通過HttpWebRequest引用訪問這個屬性。該屬性允許多個請求使用同一個連接,在後續的請求中節省關閉和重新打開連接的時間。其默認值爲true。

AllowAutoRedirect屬性也是專用於HttpWebRequest類的,使用這個屬性可以控制Web請求是否應自動跟隨Web服務器上的重定向響應。其默認值也是true。如果只允許有限的重定向,可以把HttpWebRequest的MaximumAutomaticRedirections屬性設置爲想要的數值。

請求和響應類把大多數重要的標題顯示爲屬性,也可以使用Headers屬性本身顯示標題的總集合。在GetResponse()方法調用的後面添加如下代碼,把所有的標題都放在列表框中:

WebRequest wrq = WebRequest.Create("http://www.wrox.com");

WebResponse wrs = wrq.GetResponse();

WebHeaderCollection whc = wrs.Headers;

for(int i = 0; i < whc.Count; i++)

{

    listBox1.Items.Add("Header " + whc.GetKey(i) + " : " + whc[i]);

}

這個示例代碼會產生如圖31-2所示的標題列表。

 

圖  31-2
2. 身份驗證

WebRequest類中的另一個屬性是Credentials。如果需要把身份驗證證書附帶在請求中,就可以用用戶名和密碼創建NetworkCredential類(也在System.Net命名空間中)的一個實例。在調用GetResponse()之前,添加下述代碼:

NetworkCredential myCred = new NetworkCredential("myusername", "mypassword");

wrq.Credentials = myCred;
3. 異步頁面請求

WebRequest類的另一個特性就是可以異步請求頁面。由於在給主機發送請求到接收響應之間有很長的延遲,因此,異步請求頁面就顯得比較重要。像WebClient.DownloadData()和WebRequest.GetResponse()等方法,在響應沒有從服務器回來之前,是不會返回的。如果不希望在那段時間中應用程序處於等待狀態,可以使用BeginGetResponse() 方法和 EndGetResponse()方法,BeginGetResponse()方法可以異步工作,並立即返回。在底層,運行庫會異步管理一個後臺線程,從服務器上接收響應。BeginGetResponse() 方法不返回WebResponse對象,而是返回一個執行IAsyncResult接口的對象。使用這個接口可以選擇或等待可用的響應,然後調用EndGetResponse()蒐集結果。

也可以把一個回調委託發送給BeginGetResponse()方法。該回調委託的目的地是一個返回類型爲void並把IAsyncResult引用作爲參數的方法,當工作線程完成了蒐集響應的任務後,運行庫就調用該回調委託,通知用戶工作已完成。如下面的代碼所示,在回調方法中調用EndGetResponse()可以接收WebResponse對象:

public Form1()

{

   InitializeComponent();

 

   WebRequest wrq = WebRequest.Create("http://www.wrox.com");

   wrq.BeginGetResponse(new AsyncCallback(OnResponse), wrq);     

}

 

protected void OnResponse(IAsyncResult ar)

{

   WebRequest wrq = (WebRequest)ar.AsyncState;

   WebResponse wrs = wrq.EndGetResponse(ar);

 

   // read the response ...

}

注意可以把對象傳送爲BeginGetResponse()的第二個參數,檢索最初的WebRequest對象。第三個參數是一個對象引用,稱爲狀態參數,在回調方法中,可以使用IAsyncResult的AsyncState屬性檢索相同的狀態對象。

發佈了57 篇原創文章 · 獲贊 2 · 訪問量 42萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章