HTTP協定我想任何IT人士都耳熟能詳了,大家都能說出個是以然來。但是如果我問你HTTP協定的請求方法有哪些?POST與GET的差異?GET或POST傳送資料量的大小有限制嗎?HTTP響應的狀态有哪些?以及在C#中你如何使用?如果你不能清楚地回答其中的大部分問題,那麼這篇文章就是為你準備的!大綱如下:
1、HTTP概述
1.1、HTTP協定的用戶端與伺服器的互動
1.2、HTTP消息
1.3、HTTP請求的方法
1.4、HTTP響應的代碼
2、抓包分析
3、POST與GET的差異
4、以一個執行個體說明C#中如何使用POST、GET等操作
4.1、HttpWebRequest
4.2、HttpWebResponse
4.3、編寫WinForm程式打開部落格園首頁(附源碼)
通常,由HTTP用戶端發起一個請求,建立一個到伺服器指定端口(預設是80端口)的TCP連接配接。HTTP伺服器則在那個端口監聽用戶端發送過來的請求。一旦收到請求,伺服器(向用戶端)發回一個狀态行,比如"HTTP/1.1 200 OK",和(響應的)消息,消息的消息體可能是請求的檔案、錯誤消息、或者其它一些資訊。
用戶端與伺服器端的結構與互動過程可以表示為下面2張圖:
<a target="_blank" href="http://blog.51cto.com/attachment/201008/093827242.png"></a>
圖1、Web用戶端-伺服器端結構(其中web伺服器的超文本連結,即通過網站上的一個連結跳轉到了其他伺服器上)
<a target="_blank" href="http://blog.51cto.com/attachment/201008/093919680.png"></a>
圖2、Web用戶端與伺服器端的互動
用戶端與伺服器之間的互動用到了兩種類型的消息:請求(Request)和響應(Response)。
HTTP請求的格式為:
<a target="_blank" href="http://blog.51cto.com/attachment/201008/094004763.jpg"></a>
圖3、HTTP請求的格式
HTTP響應的格式為:
<a target="_blank" href="http://blog.51cto.com/attachment/201008/094034574.jpg"></a>
圖4、HTTP響應的格式
從上面可以看出HTTP的請求和響應消息的首部均包含可變數量的字段,用一個空行(blank line)将所有首部字段(header)與消息主體(body)分隔開來。一個首部字段由字段名和随後的冒号、一個空格和字段值組成,字段名不區分大小寫。
封包頭可分為三類:一類應用于請求,一類應用于響應,還有一類描述主體。有一些封包頭(例如:Date)既可用于請求又可用于響應。描述主體的封包頭可以出現在POST請求和所有響應封包中。HTTP的首部字段如下圖所示:
<a target="_blank" href="http://blog.51cto.com/attachment/201008/094117135.png"></a>
圖5、HTTP首部字段
HTTP/1.1協定中共定義了八種方法(有時也叫“動作”)來表明Request-URI指定的資源的不同操作方式:
OPTIONS
傳回伺服器針對特定資源所支援的HTTP請求方法。也可以利用向Web伺服器發送'*'的請求來測試伺服器的功能性。
HEAD
向伺服器索要與GET請求相一緻的響應,隻不過響應體将不會被傳回。這一方法可以在不必傳輸整個響應内容的情況下,就可以擷取包含在響應消息頭中的元資訊。
GET
POST
向指定資源送出資料進行處理請求(例如送出表單或者上傳檔案)。資料被包含在請求體中。POST請求可能會導緻新的資源的建立和/或已有資源的修改。
PUT
向指定資源位置上傳其最新内容。
DELETE
請求伺服器删除Request-URI所辨別的資源。
TRACE
回顯伺服器收到的請求,主要用于測試或診斷。
CONNECT
HTTP/1.1協定中預留給能夠将連接配接改為管道方式的代理伺服器。
方法名稱是區分大小寫的。當某個請求所針對的資源不支援對應的請求方法的時候,伺服器應當傳回狀态碼405(Method Not Allowed);當伺服器不認識或者不支援對應的請求方法的時候,應當傳回狀态碼501(Not Implemented)。
HTTP伺服器至少應該實作GET和HEAD方法,其他方法都是可選的。此外,除了上述方法,特定的HTTP伺服器還能夠擴充自定義的方法。
安全方法 但是,不能想當然地認為伺服器不會在處理某個GET請求時不會産生任何副作用。事實上,很多動态資源會把這作為其特性。這裡重要的差別在于使用者并沒有請求這一副作用,是以不應由使用者為這些副作用承擔責任。 幂等方法 假如在不考慮諸如錯誤或者過期等問題的情況下,若幹次請求的副作用與單次請求相同或者根本沒有副作用,那麼這些請求方法就能夠被視作“幂等”的。GET,HEAD,PUT和DELETE方法都有這樣的幂等屬性,同樣由于根據協定,OPTIONS,TRACE都不應有副作用,是以也理所當然也是幂等的。 假如某個由若幹個請求做成的請求串行産生的結果在重複執行這個請求串行或者其中任何一個或多個請求後仍沒有發生變化,則這個請求串行便是“幂等” 的。但是,可能出現若幹個請求做成的請求串行是“非幂等”的,即使這個請求串行中所有執行的請求方法都是幂等的。例如,這個請求串行的結果依賴于某個會在下次執行這個串行的過程中被修改的變量。
伺服器程式響應的第一行叫狀态行。狀态行以HTTP版本号開始,後面跟着3位數字表示響應代碼,最後是易讀的響應短語。根據第一位可以把響應分成5類:
<a target="_blank" href="http://blog.51cto.com/attachment/201008/094302267.png"></a>
圖6、HTTP響應代碼
現在我們對HTTP基本上算是了解了,下面我用wireshark抓取打開部落格園首頁時,我的電腦與部落格園伺服器的互動過程的HTTP資料包。做好準備工作,關閉一些可能幹擾我們抓取打開部落格園的相關程式。如下圖,我們在浏覽器中輸入www.cnblogs.com并确定時,首先抓到如下包:
<a target="_blank" href="http://blog.51cto.com/attachment/201008/094457789.png"></a>
圖7、打開部落格園抓取的包
從圖中可以看出,我們在浏覽器中輸入www.cnblogs.com并确定時是向伺服器發送了一個HTTP請求消息:GET / HTTP/1.1。根據1.2中介紹的HTTP消息的格式,我們知道GET對應request、/對應request-line、HTTP/1.1對應版本号。除了請求行之外,發送了一些首部字段,如:Accept、Accept-Language、User-Agent、Accept-Encoding、Host、Connection等。而且可以看出他們的格式就是:首部字段名: 字段值,注意冒号後面有個空格。
接下來我們看一下GET / HTTP/1.1請求的響應消息是怎樣的:
<a target="_blank" href="http://blog.51cto.com/attachment/201008/094548643.png"></a>
圖8、GET / HTTP/1.1請求的響應消息
響應消息的狀态行是:HTTP/1.1 200 OK,其中HTTP/1.1對應版本号、200對應response-code、OK對應response-phrase。除了狀态行,還傳回了一些首部字段,如:Cache-Control、Content-Type、Content-Encoding、Expires、Last-Modified、Vary、Server等等。(通過上圖我們可以看出,部落格用的是IIS7.0)
上面抓的是GET的資料包,現在我來看一個POST的資料包——打開部落格園首頁過程中擷取左邊的分類資訊就是通過POST請求傳回的。
<a target="_blank" href="http://blog.51cto.com/attachment/201008/094649143.png"></a>
圖9、POST資料包
我們可以看到,POST /ws/PublicUserService.asmx/GetLoginInfo HTTP/1.1。除了把GET換成了POST之外,其它資訊差不多。下面我們放大看下發送的首部字段:
<a target="_blank" href="http://blog.51cto.com/attachment/201008/094723692.png"></a>
圖10、POST /ws/PublicUserService.asmx/GetLoginInfo HTTP/1.1的首部字段
NOTE:本節涉及的一些首部字段我就不在這裡解釋了。我想,到了這裡大家對HTTP的認識應該更深入了一步。
1.3中介紹了8種方法,其中GET與POST最基本和常用了。表單送出中get和post方式的差別歸納如下幾點:
GET是從伺服器上擷取資料,POST是向伺服器傳送資料。
GET是把參數資料隊列加到送出表單的ACTION屬性所指的URL中,值和表單内各個字段一一對應,在URL中可以看到。POST是通過HTTP POST機制,将表單内各個字段與其内容放置在HTML HEADER内一起傳送到ACTION屬性所指的URL位址。使用者看不到這個過程。
對于GET方式,伺服器端用Request.QueryString擷取變量的值,對于POST方式,伺服器端用Request.Form擷取送出的資料。
GET傳送的資料量較小,不能大于2KB(這主要是因為受URL長度限制)。POST傳送的資料量較大,一般被預設為不受限制。但理論上,限制取決于伺服器的處理能力。
GET安全性較低,POST安全性較高。因為GET在傳輸過程,資料被放在請求的URL中,而如今現有的很多伺服器、代理伺服器或者使用者代理都會将請求URL記錄到日志檔案中,然後放在某個地方,這樣就可能會有一些隐私的資訊被第三方看到。另外,使用者也可以在浏覽器上直接看到送出的資料,一些系統内部消息将會一同顯示在使用者面前。POST的所有操作對使用者來說都是不可見的。
在FORM送出的時候,如果不指定Method,則預設為GET請求(.net預設是POST),Form中送出的資料将會附加在url之後,以?分開與url分開。字母數字字元原樣發送,但空格轉換為“+”号,其它符号轉換為%XX,其中XX為該符号以16進制表示的ASCII(或ISO Latin-1)值。GET請求請送出的資料放置在HTTP請求協定頭中,而POST送出的資料則放在實體資料中;GET方式送出的資料最多隻能有2048位元組,而POST則沒有此限制。POST傳遞的參數在doc裡,也就http協定所傳遞的文本,接受時再解析參數部分。獲得參數。一般用POST比較好。POST送出資料是隐式的,GET是通過在url裡面傳遞的,用來傳遞一些不需要保密的資料,GET是通過在URL裡傳遞參數,POST不是。
說明:關于“POST與GET的差異”查考了網上前輩的資料,由于找不出源頭,到處都是轉帖,這裡就不貼出相關網址了,baidu或Google下就知道了。
在介紹執行個體之前,我們要先介紹一下HttpWebRequest和HttpWebResponse,在C#中就是用這兩個類實作用戶端向伺服器端發送HTTP消息、用戶端接受伺服器端的HTTP響應。
HTTP消息的首部字段(headers),在HttpWebRequest中表示為公開的屬性。下表列出了由屬性或方法設定或由系統設定的 HTTP 标頭。
<a target="_blank" href="http://blog.51cto.com/attachment/201008/094823552.png"></a>
如果本地計算機配置指定使用代理,或者如果請求指定代理,則使用代理發送請求。如果未指定代理,則請求發送到伺服器。
HttpWebRequest類主要包括如下方法,用于與HTTP伺服器互動:
注意
<a target="_blank" href="http://blog.51cto.com/attachment/201008/094931759.png"></a>
HttpWebRequest類主要包括如下方法與HTTP伺服器互動:(與HttpWebRequest類相比,方法較少)
通過前面兩小節的介紹,我們對HttpWebRequest類和HttpWebRequest類有所了解,現在我們就應用它們來編寫一個小程式來實踐。程式界面大概如下:
<a target="_blank" href="http://blog.51cto.com/attachment/201008/095015356.png"></a>
功能也比較簡單,就是通過點選“在WebBrowser中顯示”按鈕就在下方的 WebBrowser控件中顯示部落格園首頁,通過點選檢視“html源碼”按鈕就彈出一個對話框顯示部落格園首頁的html源碼。
首先我們介紹如何實作——通過點選檢視“html源碼”按鈕就彈出一個對話框顯示部落格園首頁的html源碼。核心代碼如下:
private string GetCnBlogs()
{
string html = String.Empty;
HttpWebRequest cnbogs = (HttpWebRequest)System.Net.WebRequest.Create(txtURL.Text.ToString());
cnbogs.Accept = "image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/QVOD, application/QVOD, */*";
cnbogs.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; MALN; CIBA; InfoPath.2; .NET4.0C; .NET4.0E; Media Center PC 6.0; Tablet PC 2.0; AskTB5.6)";
cnbogs.Method = "GET";
HttpWebResponse cnblogsRespone = (HttpWebResponse)cnbogs.GetResponse();
if (cnblogsRespone != null&&cnblogsRespone.StatusCode==HttpStatusCode.OK)
{
using(StreamReader sr = new StreamReader(cnblogsRespone.GetResponseStream()))
{
html = sr.ReadToEnd();
}
}
return html;
}
private void btnGetHtml_Click(object sender, EventArgs e)
MessageBox.Show(GetCnBlogs());
}
其實這個過程更我們通過在浏覽器中輸入部落格園網站打開效果是一樣的,隻不過在這裡我們是通過HttpWebRequest類和HttpWebRequest類的對象來實作的。
我這個源碼還是比較簡陋,隻是簡單地實作了使用HttpWebRequest類和HttpWebRequest類與HTTP伺服器互動,更完善的功能期待你去完成。
參考:寫此文章時,我參閱了不少文章,我列舉其中印象比較深的
TCP/IP協定詳解卷3
本文轉自Saylor87 51CTO部落格,原文連結:http://blog.51cto.com/skynet/366055,如需轉載請自行聯系原作者