Visual C# HTTP協議開發
- HTTP協議簡介
- HTTP協議簡介
- HTTP的請求
- HTTP的響應
- 與HTTP相關類的簡介
- WebRequest類
- WebResponse類
- HttpWebRequest類
- HttpWebResponse類
- Uri類
HTTP協議簡介HTTP協議簡介
在TCP/IP體繫結構中,HTTP屬於應用程式層協議,位於TCP/IP協議的頂層。瀏覽Web時,瀏覽器通過HTTP協議與Web伺服器交換資訊。這些資訊(文檔)類型的格式由MIME定義。
HTTP協議具有以下的特點:
- HTTP按客戶/伺服器模式工作
HTTP支援客戶(一般情況是瀏覽器)與伺服器的通訊,相互傳輸資料。
HTTP定義的交易處理由以下四步組成:
- 客戶與伺服器建立串連;
- 客戶向伺服器提出請求;
- 如果請求被接受,則伺服器送迴響應,在響應中包括狀態代碼和所需的檔案;
- 客戶與伺服器中斷連線
| 一次HTTP操作稱為一次事務(transaction)。 |
- HTTP是無狀態的
也就是說,瀏覽器和伺服器每進行一次HTTP操作,就建立一次串連,但任務結束就中斷串連。
- HTTP使用元資訊作為頭標
HTTP對所有事務都加了頭標(header)。也就是說,在主要資料前加上一塊資訊,稱為元資訊(metainformation)。它使伺服器能夠提供正在傳送資料的有關資訊。例如,傳送對象是哪種類型,是用哪種語言書寫的等。
從功能上講,HTTP支援四類元資訊:一般資訊頭標、要求標頭標、回應標頭標和實體頭標。
- HTTP支援兩種請求和響應格式
HTTP由不同的兩部分組成,一是從瀏覽器發往伺服器的請求,二是伺服器對客戶的響應。
HTTP支援兩種請求和響應,即簡單請求與完全請求和簡單響應與完全響應。
- HTTP是基於文本的簡單協議
HTTP的請求
HTTP的常用要求方法:
| 方 法 |
說 明 |
| GET |
請求讀取一個Web頁面 |
| HEAD |
請求讀取一個Web頁面的頭標 |
| PUT |
請求儲存一個Web頁面 |
| POST |
附加到命名資源中 |
| DELETE |
刪除Web頁面 |
| LINK |
串連兩個已有資源 |
| UNLINK |
取消兩個資源之間的已有串連 |
HTTP請求的格式如下所示:
<request-line>
<headers>
<blank line>
[<request-body>]
在HTTP請求中,第一行必須是一個請求行(request line),用來說明請求類型、要訪問的資源以及使用的HTTP版本。緊接著是一個首部(header)小節,用來說明伺服器要使用的附加資訊。在首部之後是一個空行,再此之後可以添加任意的其他資料[稱之為主體(body)]。
在HTTP中,定義了大量的請求類型,不過Ajax開發人員關心的只有GET請求和POST請求。只要在Web瀏覽器上輸入一個URL,瀏覽器就將基於該URL向伺服器發送一個GET請求,以告訴伺服器擷取並返回什麼資源。對於www.wzu.edu.cn的GET請求如下所示:
GET / HTTP/1.1
Host: www.wzu.edu.cn
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US;
rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
請求行的第一部分說明了該請求是GET請求。該行的第二部分是一個斜杠(/),用來說明請求的是該網域名稱的根目錄。該行的最後一部分說明使用的是HTTP 1.1版本(另一個可選項是1.0)。那麼請求發到哪裡去呢?這就是第二行的內容。
第2行是請求的第一個首部,HOST。首部HOST將指出請求的目的地。結合HOST和上一行中的斜杠(/),可以通知伺服器請求的是www.wzu.edu.cn/(HTTP 1.1才需要使用首部HOST,而原來的1.0版本則不需要使用)。第三行中包含的是首部User-Agent,伺服器端和用戶端指令碼都能夠訪問它,它是瀏覽器類型檢測邏輯的重要基礎。該資訊由你使用的瀏覽器來定義(在本例中是Firefox 1.0.1),並且在每個請求中將自動發送。最後一行是首部Connection,通常將瀏覽器操作設定為Keep-Alive(當然也可以設定為其他值,但這已經超出了本書討論的範圍)。注意,在最後一個首部之後有一個空行。即使不存在請求主體,這個空行也是必需的。
如果要擷取一個諸如http://www.wzu.edu.cn/books的www.wzu.edu.cn域內的頁面,那麼該請求可能類似於:
GET /books/
HTTP/1.1
Host: www.wzu.edu.cn
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US;
rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
注意只有第一行的內容發生了變化,它只包含URL中www.wzu.edu.cn後面的部分。
要發送GET請求的參數,則必須將這些額外的資訊附在URL本身的後面。其格式類似於:
URL ? name1=value1&name2=value2&..&nameN=valueN
該資訊稱之為查詢字串(query string),它將會複製在HTTP請求的請求行中,如下所示:
GET /books/?name=Professional%20Ajax
HTTP/1.1
Host: www.wzu.edu.cn
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US;
rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
另一方面,POST請求在請求主體中為伺服器提供了一些附加的資訊。通常,當填寫一個線上表單並提交它時,這些填入的資料將以POST請求的方式發送給伺服器。
以下就是一個典型的POST請求:
POST / HTTP/1.1
Host: www.wzu.edu.cn
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US;
rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive
name=Professional%20Ajax&publisher=Wiley
從上面可以發現, POST請求和GET請求之間有一些區別。首先,請求行開始處的GET改為了POST,以表示不同的請求類型。你會發現首部Host和User-Agent仍然存在,在後面有兩個新行。其中首部Content-Type說明了請求主體的內容是如何編碼的。瀏覽器始終以application/ x-www-form- urlencoded的格式編碼來傳送資料,這是針對簡單URL編碼的MIME類型。首部Content-Length說明了請求主體的位元組數。在首部Connection後是一個空行,再後面就是請求主體。與大多數瀏覽器的POST請求一樣,這是以簡單的“名稱—值”對的形式給出的,其中name是Professional
Ajax,publisher是Wiley。你可以以同樣的格式來組織URL的查詢字串參數。
正如前面所提到的,還有其他的HTTP請求類型,它們遵從的基本格式與GET請求和POST請求相同。下一步我們來看看伺服器將對HTTP請求發送什麼響應。
HTTP響應
如下所示,HTTP響應的格式與請求的格式十分類似:
<status-line>
<headers>
<blank line>
[<response-body>]
正如你所見,在響應中唯一真正的區別在於第一行中用狀態資訊代替了請求資訊。狀態行(status line)通過提供一個狀態代碼來說明所請求的資源情況。以下就是一個HTTP響應的例子:
HTTP/1.1 200
OK
Date: Sat, 31 Dec 2005 23:59:59 GMT
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 122
<html>
<head>
<title>Wrox Homepage</title>
</head>
<body>
<!-- body goes here -->
</body>
</html>
在本例中,狀態行給出的HTTP狀態碼是200,以及訊息OK。狀態行始終包含的是狀態代碼和相應的簡短訊息,以避免混亂。最常用的狀態代碼有:
- 200 (OK): 找到了該資源,並且一切正常。
- 304 (NOT MODIFIED): 該資源在上次請求之後沒有任何修改。這通常用於瀏覽器的緩衝機制。
- 401 (UNAUTHORIZED):用戶端無權訪問該資源。這通常會使得瀏覽器要求使用者輸入使用者名稱和密碼,以登入到伺服器。
- 403 (FORBIDDEN):用戶端未能獲得授權。這通常是在401之後輸入了不正確的使用者名稱或密碼。
- 404 (NOT FOUND):在指定的位置不存在所申請的資源。
在狀態行之後是一些首部。通常,伺服器會返回一個名為Date的首部,用來說明響應產生的日期和時間(伺服器通常還會返回一些關於其自身的資訊,儘管並非是必需的)。接下來的兩個首部大家應該熟悉,就是與POST請求中一樣的Content-Type和Content-Length。在本例中,首部Content-Type指定了MIME類型HTML(text/html),其編碼類別型是ISO-8859-1(這是針對美國英語資源的編碼通訊協定)。響應主體所包含的就是所請求資源的HTML源檔案(儘管還可能包含純文字或其他資源類型的位元據)。瀏覽器將把這些資料顯示給使用者。
注意,這裡並沒有指明針對該響應的請求類型,不過這對於伺服器並不重要。用戶端知道每種類型的請求將返回什麼類型的資料,並決定如何使用這些資料。
與HTTP相關類的簡介WebRequest類
WebRequest 是 .NET Framework 的用於訪問 Internet 資料的請求/響應模型的抽象基類。使用該請求/響應模型的應用程式可以用協議不可知的方式從 Internet 請求資料。在這種方式下,應用程式處理 WebRequest 類的執行個體,而協議特定的子類則執行請求的具體細節。
請求從應用程式發送到某個特定的 URI,如伺服器上的 Web 頁。URI 從一個為應用程式註冊的 WebRequest 子代列表中確定要建立的適當子類。註冊WebRequest 子代通常是為了處理某個特定的協議(如 HTTP 或 FTP),但是也可以註冊它以處理對特定伺服器或伺服器上的路徑的請求。
由於 WebRequest 類是一個抽象類別,所以 WebRequest 執行個體在運行時的實際行為由 WebRequest.Create 方法所返回的子類確定。
注意 使用 Create 方法初始化新的 WebRequest 執行個體。不要使用 WebRequest 建構函式。
下面的樣本說明如何建立 WebRequest 執行個體並返迴響應。
// Initialize
the WebRequest.
WebRequest myRequest = WebRequest.Create("http://www.contoso.com");
// Return
the response.
WebResponse myResponse = myRequest.GetResponse();
// Code
to use the WebResponse goes here.
// Close
the response to free resources.
myResponse.Close();WebResponse類
WebResponse 類是抽象(在 Visual Basic 中為 MustInherit)基類,協議特定的響應類從該抽象基類派生。應用程式可以使用 WebResponse 類的執行個體以協議不可知的方式參與請求和響應事務,而從 WebResponse 派生的協議特定的類攜帶請求的詳細資料。
用戶端應用程式不直接建立 WebResponse 對象,而是通過調用 WebRequest 執行個體上的 GetResponse 方法來建立它。
下面的樣本從 WebRequest 建立 WebResponse 執行個體。
// Initialize
the WebRequest.
WebRequest myRequest = WebRequest.Create("http://www.contoso.com");
// Return
the response.
WebResponse myResponse = myRequest.GetResponse();
// Code
to use the WebResponse goes here.
// Close
the response to free resources.
myResponse.Close();HttpWebRequest類
HttpWebRequest 類對 WebRequest 中定義的屬性和方法提供支援,也對使使用者能夠直接與使用 HTTP 的伺服器互動的附加屬性和方法提供支援。
不要使用 HttpWebRequest 建構函式。使用 WebRequest.Create 方法初始化 HttpWebRequest 的一個新執行個體。如果 URI 的方案是 http:// 或 https://,則Create 將返回 HttpWebRequest 執行個體。
GetResponse 方法向 RequestUri 屬性中指定的 Internet 資源發出同步請求並返回包含該響應的 HttpWebResponse 執行個體。可以使用 BeginGetResponse 和EndGetResponse 方法對
Internet 資源發出非同步請求。
當要向 Internet 資源發送資料時,GetRequestStream 方法返回用於發送資料的Stream執行個體。BeginGetRequestStream 和 EndGetRequestStream 方法提供對發送資料流的非同步訪問。
下面的樣本為 URI http://www.contoso.com/ 建立 HttpWebRequest。
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create("http://www.contoso.com/");HttpWebResponse類
此類包含對 WebResponse 類中的屬性和方法的 HTTP 特定用法的支援。HttpWebResponse 類用於產生發送 HTTP 要求和接收 HTTP 響應的 HTTP 獨立用戶端應用程式。
注意:不要混淆 HttpWebResponse 和 HttpResponse;後者用於
ASP.NET 應用程式,而且它的方法和屬性是通過 ASP.NET 的內部 HttpResponse 對象公開的。
決不要直接建立 HttpWebResponse 類的執行個體。而應當使用通過調用 HttpWebRequest.GetResponse 所返回的執行個體。
從 Internet 資源返回的公用標題資訊公開為該類的屬性。有關完整的列表,請參見下表。可以從 Headers 屬性以成對的名稱和數值的形式讀取其他標題。
下表顯示可以通過 HttpWebResponse 類的屬性使用的公用 HTTP 標題。
| 標題 |
屬性 |
| Content-Encoding |
ContentEncoding |
| Content-Length |
ContentLength |
| Content-Type |
ContentType |
| Last-Modified |
LastModified |
| 伺服器 |
Server |
通過調用 GetResponseStream 方法,以 Stream 的形式返回來自 Internet 資源的響應的內容。
下面的樣本返回 HttpWebRequest 的 HttpWebResponse:
HttpWebRequest HttpWReq = (HttpWebRequest)WebRequest.Create("http://www.contoso.com");HttpWebResponse HttpWResp = (HttpWebResponse)HttpWReq.GetResponse();// Insert code that uses the response object.HttpWResp.Close()Uri類
URI 是 Internet 上可由應用程式使用的資源的簡潔表示形式。Uri 類定義了屬性和方法來處理 URI,包括分析、比較和組合。Uri 類屬性是唯讀,修改 Uri 執行個體需使用 UriBuilder 類。
Uri 類只儲存絕對 URI(例如“http://www.contoso.com/index.htm”)。相對 URI(例如“/new/index.htm”)必須相對於基 URI 展開,這樣才是絕對的。提供了MakeRelative 方法在必要時將絕對 URI 轉換為相對 URI。
URI 由轉義編碼儲存為正常化 URI,所有 ASCII 值大於 127 的字元都被替換為它們的等效十六進位數。為使 URI 具有正常化格式,Uri 建構函式執行以下步驟。
- 將 URI 方案轉換為小寫。
- 將主機名稱轉換為小寫。
- 移除預設連接埠號碼和空連接埠號碼。
- 移除多餘的段(如“/”和“/test”段)以簡化 URI。
使用 ToString 方法,可以將 Uri 類的內容從轉義編碼的 URI 引用轉換為可讀的 URI 引用。
一些 URI 包括段標識符或查詢。段標識符是 URI 中跟在數字記號 (#) 後的任何文本,儲存在 Fragment 屬性中。查詢資訊是 URI 中跟在問號 (?) 後的任何文本,儲存在 Query 屬性中。
注意:URI 類支援使用以下格式的 IP 位址:四組標記法的 IPv4 協議和冒號分隔的十六進位 IPv6 協議。請記住在 IPv6 地址兩邊括上方括弧,如 http://[::1]。
下面的樣本建立 Uri 類的執行個體,並用它來建立 WebRequest。
Uri siteUri = new Uri("http://www.contoso.com/");
WebRequest wr = WebRequest.Create(siteUri);