1. 程式人生 > >基於c#的http協議學習

基於c#的http協議學習

轉載於https://www.cnblogs.com/jiang08/articles/3946015.html

跪謝!

 

在TCP/IP體系結構中,HTTP屬於應用層協議,位於TCP/IP協議的頂層。瀏覽Web時,瀏覽器通過HTTP協議與Web伺服器交換資訊。這些資訊(文件)型別的格式由MIME定義。

HTTP協議具有以下的特點:

1.   HTTP按客戶/伺服器模式工作 HTTP支援客戶(一般情況是瀏覽器)與伺服器的通訊,相互傳輸資料。 HTTP定義的事務處理由以下四步組成:

·        客戶與伺服器建立連線;

·        客戶向伺服器提出請求;

·        如果請求被接受,則伺服器送回響應,在響應中包括狀態碼和所需的檔案;

·        客戶與伺服器斷開連線

一次HTTP操作稱為一次事務(transaction)。

2.   HTTP是無狀態的 也就是說,瀏覽器和伺服器每進行 一次HTTP

操作,就建立一次連線,但任務結束就中斷連線。

3.   HTTP使用元資訊作為頭標 HTTP對所有事務都加了頭標(header)。也就是說,在主要資料前加上一塊資訊,稱為元資訊(metainformation)。它使伺服器能夠提供正在傳送資料的有關資訊。例如,傳送物件是哪種型別,是用哪種語言書寫的等。 從功能上講,HTTP支援四類元資訊:一般資訊頭標、請求頭標、響應頭標和實體頭標。

4.   HTTP支援兩種請求和響應格式 HTTP由不同的兩部分組成,一是從瀏覽器發往伺服器的請求,二是伺服器對客戶的響應。 HTTP支援兩種請求和響應,即簡單請求與完全請求和簡單響應與完全響應。

5.   HTTP是基於文字的簡單協議

 

 

HTTP的常用請求方法:

GET

請求讀取一個Web頁面

HEAD

請求讀取一個Web頁面的頭標

PUT

請求儲存一個Web頁面

POST

附加到命名資源中

DELETE

刪除Web頁面

LINK

連線兩個已有資源

UNLINK

取消兩個資源之間的已有連線

 

 HTTP請求的格式如下所示:

request-line //請求行(request line),用來說明請求型別、要訪問的資源以及使用的HTTP版本

headers//首部(header)小節,用來說明伺服器要使用的附加資訊

 

blank line//首部之後是一個空行

 

[request-body] 其他資料[稱之為主體(body)]

只要在Web瀏覽器上輸入一個URL,瀏覽器就將基於該URL向伺服器傳送一個GET請求,以告訴伺服器獲取並返回什麼資源。對於URL為XXX的GET請求如下所示:

GET / HTTP/1.1  //該請求是GET請求。該行的第二部分是一個斜槓(/)用來說明請求的是該域名的根目錄。該行的最後一部分說明使用的是HTTP 1.1版本

Host: XXX //首部HOST將指出請求的目的地。結合HOST和上一行中的斜槓(/),可以通知伺服器請求的是XXX

User-Agent: Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv:1.7.6)   //第三行中包含的是首部User-Agent,伺服器端和客戶端指令碼都能夠訪問它,它是瀏覽器型別檢測邏輯的重要基礎。該資訊由你使用的瀏覽器來定義(在本例中是Firefox 1.0.1),並且在每個請求中將自動傳送。

Gecko/20050225 Firefox/1.0.1 //在本例中是Firefox 1.0.1

Connection: Keep-Alive  //首部Connection,通常將瀏覽器操作設定為Keep-Alive)

                       //注意,在最後一個首部之後有一個空行。即使不存在請求主體,這個空行也是必需的。

 

 

如果要獲取一個諸如XXX/xxx的XXX域內的頁面,那麼該請求可能類似於:

GET /xxx/ HTTP/1.1

Host: XXX

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中XXX後面的部分。

要傳送GET請求的引數,則必須將這些額外的資訊附在URL本身的後面。其格式類似於:

URL ?name1=value1&name2=value2&..&nameN=valueN

該資訊稱之為查詢字串(query string),它將會複製在HTTP請求的請求行中,如下所示:

 

GET /xxx/?name=Professional%20Ajax HTTP/1.1

Host: XXX

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 / HTTP/1.1//請求行開始處的GET改為了POST,以示不同。

Host: XXX  //URL

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-Type說明了請求主體的內容是如何編碼的,瀏覽器始終以application/x-www-form- urlencoded的格式編碼來傳送資料,這是針對簡單URL編碼的MIME型別(text/html)

Content-Length: 40 //Content-Length說明了請求主體的位元組數

Connection: Keep-Alive

//首部Connection後是一個空行,再後面就是請求主體

name=Professional%20Ajax&publisher=Wiley //以鍵值對的形式給出,其中name是Professional Ajax,publisher是Wiley。你可以以同樣的格式來組織URL的查詢字串引數。

 

正如前面所提到的,還有其他的HTTP請求型別,它們遵從的基本格式與GET請求和POST請求相同。下一步我們來看看伺服器將對HTTP請求傳送什麼響應。

HTTP響應

如下所示,HTTP響應的格式與請求的格式十分類似:

status-line

headers

blank line

[response-body]

響應中唯一的區別在於第一行中用狀態資訊代替了請求資訊。狀態行(statusline)通過提供一個狀態碼來說明所請求的資源情況。

 

 

以下就是一個HTTP響應的例子:

HTTP/1.1200 OK  //狀態行給出的HTTP狀態程式碼是200,以及訊息OK

Date: Sat, 31 Dec 200523:59:59 GMT //狀態行之後是一些首部,通常,伺服器會返回一個名為Date的首部,用來說明響應生成的日期和時間(伺服器通常還會返回一些關於其自身的資訊,儘管並非是必需的)

//接下來的兩個首部大家應該熟悉,就是與POST請求中一樣的Content-Type和Content-Length。在本例中,首部Content-Type指定了MIME型別HTML(text/html),其編碼型別是ISO-8859-1(這是針對美國英語資源的編碼標準)

Content-Type: text/html;charset=ISO-8859-1

Content-Length: 122

 

html

head

titleWrox Homepage/title

/head

body

!-- body goes here--

/body

/html

狀態行始終包含的是狀態碼和相應的簡短訊息,以避免混亂。最常用的狀態碼有:

·        200 (OK): 找到了該資源,並且一切正常。

·        304 (NOT MODIFIED): 該資源在上次請求之後沒有任何修改。這通常用於瀏覽器的快取機制。

·        401 (UNAUTHORIZED):客戶端無權訪問該資源。這通常會使得瀏覽器要求使用者輸入使用者名稱和密碼,以登入到伺服器。

·        403 (FORBIDDEN):客戶端未能獲得授權。這通常是在401之後輸入了不正確的使用者名稱或密碼。

·        404 (NOT FOUND):在指定的位置不存在所申請的資源。

 

響應主體所包含的就是所請求資源的HTML原始檔(儘管還可能包含純文字或其他資源型別的二進位制資料)。瀏覽器將把這些資料顯示給使用者。注意,這裡並沒有指明針對該響應的請求型別,不過這對於伺服器並不重要。客戶端知道每種型別的請求將返回什麼型別的資料,並決定如何使用這些資料。

HTTP認證

基本認證 basic authentication

    客戶端對於每一個realm,通過提供使用者名稱和密碼來進行認證的方式。

    ※ 包含密碼的明文傳遞

 

    基本認證步驟:

     1. 客戶端訪問一個受http基本認證保護的資源。

     2. 伺服器返回401狀態,要求客戶端提供使用者名稱和密碼進行認證。

          401 Unauthorized

          WWW-Authenticate Basic realm="WallyWorld"

     3. 客戶端將輸入的使用者名稱密碼用Base64進行編碼後,採用非加密的明文方式傳送給伺服器。

          Authorization: Basic xxxxxxxxxx.

     4. 如果認證成功,則返回相應的資源。如果認證失敗,則仍返回401狀態,要求重新進行認證。

 

    特記事項:

     1. Http是無狀態的,同一個客戶端對同一個realm內資源的每一個訪問會被要求進行認證。

     2. 客戶端通常會快取使用者名稱和密碼,並和authenticationrealm一起儲存,所以,一般不需要你重新輸入使用者名稱和密碼。

     3. 以非加密的明文方式傳輸,雖然轉換成了不易被人直接識別的字串,但是無法防止使用者名稱密碼被惡意盜用。

    特記事項:

     1. Http是無狀態的,同一個客戶端對同一個realm內資源的每一個訪問會被要求進行認證。

     2. 客戶端通常會快取使用者名稱和密碼,並和authenticationrealm一起儲存,所以,一般不需要你重新輸入使用者名稱和密碼。

     3. 以非加密的明文方式傳輸,雖然轉換成了不易被人直接識別的字串,但是無法防止使用者名稱密碼被惡意盜用。

 

  摘要認證 digest authentication

    伺服器端以nonce進行質詢,客戶端以使用者名稱,密碼,nonce,HTTP方法,請求的URI等資訊為基礎產生的response資訊進行認證的方式。

    ※ 不包含密碼的明文傳遞

    

    摘要認證步驟:

     1. 客戶端訪問一個受http摘要認證保護的資源。

     2. 伺服器返回401狀態以及nonce等資訊,要求客戶端進行認證。

 

HTTP/1.1401 Unauthorized

WWW-Authenticate: Digest

realm="[email protected]",//響應中包含資訊

qop="auth,auth-int",

nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",//響應中包含的資訊

opaque="5ccc069c403ebaf9f0171e9517f40e41"

 

     3. 客戶端將以使用者名稱,密碼,nonce值,HTTP方法, 和被請求的URI為校驗值基礎而加密(預設為MD5演算法)的摘要資訊返回給伺服器。

          認證必須的五個情報:

     ・ realm : 響應中包含資訊

     ・ nonce : 響應中包含資訊

     ・ username : 使用者名稱

     ・ digest-uri : 請求的URI

     ・ response : 以上面四個資訊加上密碼資訊,使用MD5演算法得出的字串。

    特記事項:

     1. Http是無狀態的,同一個客戶端對同一個realm內資源的每一個訪問會被要求進行認證。

     2. 客戶端通常會快取使用者名稱和密碼,並和authenticationrealm一起儲存,所以,一般不需要你重新輸入使用者名稱和密碼。

     3. 以非加密的明文方式傳輸,雖然轉換成了不易被人直接識別的字串,但是無法防止使用者名稱密碼被惡意盜用。



Authorization: Digest

username="Mufasa", 客戶端已知資訊

realm="[email protected]",  伺服器端質詢響應資訊

nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",  伺服器端質詢響應資訊

uri="/dir/index.html", ← 客戶端已知資訊

qop=auth,  伺服器端質詢響應資訊

nc=00000001, ← 客戶端計算出的資訊

cnonce="0a4f113b", ← 客戶端計算出的客戶端nonce

response="6629fae49393a05397450978507c4ef1", ← 最終的摘要資訊 ha3

opaque="5ccc069c403ebaf9f0171e9517f40e41" 伺服器端質詢響應資訊

    特記事項:

     1. Http是無狀態的,同一個客戶端對同一個realm內資源的每一個訪問會被要求進行認證。

     2. 客戶端通常會快取使用者名稱和密碼,並和authenticationrealm一起儲存,所以,一般不需要你重新輸入使用者名稱和密碼。

     3. 以非加密的明文方式傳輸,雖然轉換成了不易被人直接識別的字串,但是無法防止使用者名稱密碼被惡意盜用。

 

  4. 如果認證成功,則返回相應的資源。如果認證失敗,則仍返回401狀態,要求重新進行認證。

 

    特記事項:

     1. 避免將密碼作為明文在網路上傳遞,相對提高了HTTP認證的安全性。

     2. 當用戶為某個realm首次設定密碼時,伺服器儲存的是以使用者名稱,realm,密碼為基礎計算出的雜湊值(ha1),而非密碼本身。

     3. 如果qop=auth-int,在計算ha2時,除了包括HTTP方法,URI路徑外,還包括請求實體主體,從而防止PUT和POST請求表示被人篡改。

     4. 但是因為nonce本身可以被用來進行摘要認證,所以也無法確保認證後傳遞過來的資料的安全性。

   nonce:隨機字串,每次返回401響應的時候都會返回一個不同的nonce 

   nounce:隨機字串,每個請求都得到一個不同的nounce 

       ※ MD5(Message Digestalgorithm 5,資訊摘要演算法)

         ① 使用者名稱:realm:密碼 ha1

         ② HTTP方法:URI ha2

         ③ha1:nonce:nc:cnonce:qop:ha2 ha3

 

    特記事項:

     1. Http是無狀態的,同一個客戶端對同一個realm內資源的每一個訪問會被要求進行認證。

     2. 客戶端通常會快取使用者名稱和密碼,並和authenticationrealm一起儲存,所以,一般不需要你重新輸入使用者名稱和密碼。

     3. 以非加密的明文方式傳輸,雖然轉換成了不易被人直接識別的字串,但是無法防止使用者名稱密碼被惡意盜用。

 

 WSSE(WS-Security)認證

    WSSE UsernameToken

    伺服器端以nonce進行質詢,客戶端以使用者名稱,密碼,nonce,HTTP方法,請求的URI等資訊為基礎產生的response資訊進行認證的方式。

    ※ 不包含密碼的明文傳遞

    

    WSSE認證步驟:

     1. 客戶端訪問一個受WSSE認證保護的資源。

     2. 伺服器返回401狀態,要求客戶端進行認證。

HTTP/1.1401 Unauthorized 

WWW-Authenticate: WSSE  

realm="[email protected]"

profile="UsernameToken" 伺服器期望你用UsernameToken規則生成迴應 

 

※ UsernameToken規則:客戶端生成一個nonce,然後根據該nonce,密碼和當前日時來算出雜湊值。

     3. 客戶端將生成一個nonce值,並以該nonce值,,當前日時為,算出雜湊返回器。

Authorization: WSSE profile="UsernameToken" 

X-WSSE:UsernameToken 

username="Mufasa"

PasswordDigest="Z2Y......"

Nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093"

Created="2010-01-01T09:00:00Z" 

 

     4. 如果認證成功,則返回相應的資源。如果認證失敗,則仍返回401狀態,要求重新進行認證。

 

    特記事項:

     1. 避免將密碼作為明文在網路上傳遞。

     2. 不需要在伺服器端作設定。

     3. 伺服器端必須儲存密碼本身,否則無法進行身份驗證。

 

 

    特記事項:

     1. Http是無狀態的,同一個客戶端對同一個realm內資源的每一個訪問會被要求進行認證。

     2. 客戶端通常會快取使用者名稱和密碼,並和authenticationrealm一起儲存,所以,一般不需要你重新輸入使用者名稱和密碼。

     3. 以非加密的明文方式傳輸,雖然轉換成了不易被人直接識別的字串,但是無法防止使用者名稱密碼被惡意盜用。

 

 

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("xxx"); 

// 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("xxx"); 

// 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 xxx 建立 HttpWebRequest

HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create("xxx"); 


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("xxx"); 

HttpWebResponse HttpWResp =(HttpWebResponse)HttpWReq.GetResponse(); 

// Insert code that uses the response object. 

HttpWResp.Close()

 

URI類

URI 是 Internet 上可由應用程式使用的資源的簡潔表示形式。Uri 類定義了屬性和方法來處理 URI,包括分析、比較和組合。Uri 類屬性是隻讀的,修改 Uri 例項需使用UriBuilder 類。

Uri 類只儲存絕對 URI。相對 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("xxx");  

WebRequest wr = WebRequest.Create(siteUri);