C#基礎之HTTP入門(一)——HTTP基礎知識

一.前言

還記得第一次去找工作的時候,來到杭州某某智慧醫療公司,面試的時候,那邊的技術總監就問了一個HTTP的OSI的模型有幾層。每每說到這個OSI模型,我就想起我大學的計算機網絡這門課是在睡夢中渡過的。依稀記得老師姓熊,除了老師的名字以外,整門課我現在都記不得,與其說把知識都還給老師了,還不如說是壓根就沒有學好。

"請問一下,HTTP的OSI模型有幾層?"面試官看了一下手中的簡歷問道。

"應該是5層吧!?"我心中忐忑,因爲我只知道OSI的模型是七層,但是對於HTTP的OSI有幾層我真的一頭霧水,"好像我的大學老師說是5層的。"

"那你的大學老師確實有點水。"面試官看了我一眼不知道說什麼好。

"我記得是5層的....應該沒錯吧?"我反駁道,聽到老師被別人說,心裏有一點點不甘心。

......

說來好玩,後面我和那個面試官爭的面紅耳赤。

最後的結果當然是沒有通過面試,但是我並沒有爲我回答了錯誤的答案而感到一點羞愧,因爲我並不是來應聘網絡工程師的,對於OSI什麼的究竟對於HTTP有什麼用,我當時真的不是很想去考究。

言歸正傳,我說上面的列子不是來噴那個面試官的,其實想說的就是我寫的這篇文章僅僅是HTTP在C#的一些皮毛,就像我當時面試的時候懵懂無知一樣,也許看完我這篇文章之後,小夥伴們可能已經會用HTTP了,但不代表真的是理解的透徹。如果想要學習,可能要找更多的資料和書籍進行翻閱學習。


二.HTTP簡介


(1)HTTP的由來

HTTP即爲HyperText Transfer Protocol的英文的縮寫,中文翻譯是超文本傳輸協議或者翻譯爲超文件傳輸協議,它是一種因特網上比較流行的傳輸協議。

HTTP最初用來發布和接收由文本組成的HTML網頁頁面的協議方法,後來才逐漸從只能傳輸文本數據,到可以傳輸圖片文件、影視頻文件,以及各種壓縮、程序文件等各種文件數據。


(2)HTTP協議版本

目前使用的基本上都是HTTP/1.1版本。如下圖,在訪問百度的時候發的GET請求用的HTTP版本爲HTTP/1.1:


(3)HTTP協議所在OSI層次

HTTP屬於應用層,位於TCP/IP的頂層。如下圖:

由上圖可知,HTTP是基於TCP的爲基礎的進行工作的,所以HTTP不會出現數據丟失和數據亂序的情況。客戶端通過TCP建立的鏈接後,用套接字發送HTTP,同理通過套接字接收HTTP的請求響應。


(4)HTTP發送請求過程

主要的過程如下:

1. 客戶端與服務器建立TCP鏈接

2. 客戶端向服務器發送請求,如果服務器接收請求,則回送響應碼和所需的信息數據,響應的過程是一個異步於其他的過程的過程

3. 重複第二步,直到客戶端將要和服務器斷開鏈接

4. 客戶端與服務器斷開鏈接

注意:HTTP/1.1支持持久鏈接,在客戶端發送一個請求直到收到響應之前,可以再次發送多個請求,即在完成一個請求和接收一個應答之後,還可以多次在這之後或者並列的完成多次"請求—應答";而對於HTTP/1.0則不支持持久鏈接。


(5)HTTP的特點

1. 以TCP的方式工作,上面已經分析;

2. HTTP是無狀態的,即服務器不會存儲關於客戶端的任何狀態信息,也不會保存客戶端的請求究竟是何種請求類型。如果一個客戶端請求兩次相同的內容,服務器也會進行兩次返回請求的對象內容,而不管原來是不是已經向客戶端發送過這個請求的對象;

3. HTTP使用元信息作爲標頭,即在請求的主體之前添加一部分信息,我們把這一部分數據稱之爲元信息(Metainfotmation),對於源信息所在的部分,我們稱之爲標頭(Header),上面第一個圖中的Request Header即爲我們請求百度頁面的標頭,其中的"Host: www.baidu.com"和"Connection: keep-Alive"等信息都屬於元信息;


(6)HTTP/1.0和HTTP/1.1之間的區別

  HTTP/1.0 HTTP/1.1
請求類型 請求類型比1.1的版本少的多,定義了基本的請求類型:GET請求、POST請求和HEAD請求 提供了8種請求類型:GET請求、POST請求、PUT請求、HEAD請求、DELETE請求、OPTIONS請求、TRACE請求和CONNECT請求。
是否支持長鏈接 不支持 支持
標頭結構 無要求,標頭不需要Host部分 標頭部分必須有Host部分,其它都是可選部分
現使用情況 幾乎不再使用 絕大部分瀏覽器和服務器都使用1.1版本


 

 

 

 

 

 


三.HTTP的請求與相應簡述(重要)


(1)Web頁面的構成

Web頁面即網頁頁面由多個頁面元素構成,我們把這些元素稱之爲對象或者是資源,這些對象或者資源在Web頁面上由單個URL所引用,我們可以通過URL來找到訪問這些對象的地址路徑,進而來訪問這些對象。特別的,我們把Web頁面的源HTML文件也看作一個對象,即一個Web頁面由其自身的源HTML文件和其頁面上引用的其他對象資源文件所構成。如果一個頁面中包含1個視頻,1個字幕,3張圖片,那麼這個頁面由6個對象構成。


(2)HTTP/1.1請求的種類

我們將GET、POST等的請求類型也稱之爲請求的方法。HTTP 1.1提供瞭如下表8種類型的請求方法:

請求的方法名 說明
GET

請求獲取特定的資源,例如,請求一個Web頁面

POST 請求向指定資源提交數據進行處理(例如,提交表單或者上傳文件),請求的數據被包含在請求體中
PUT 向指定資源位置上傳其最新內容,例如,請求儲存一個Web頁面
HEAD 向服務器請求獲取與GET請求相一致的響應,只不過響應體將不會被返回。這一方法可以在不必傳輸整個響應內容的情況下,就可以獲取包含在響應消息頭中的源信息。
DELETE 請求刪除指定的資源
OPTIONS 返回服務器正對特定資源所支持的HTTP請求方法
TRACE 回顯服務器收到的請求
CONNECT 預留給能夠將連接改爲管道方式的代理服務器


 

 

 

 

 

 

 

 

 

我們在上表中最常用的方法就是GET方法和POST方法,也稱之爲GET請求和POST請求。

注意:1. 如果服務器不支持或者客戶端發送了錯誤的請求方法,服務器會返回錯誤並立即關閉連接;

           2. 請求的名稱是區分大小寫的,一般以大寫的方式表示;

           3. 對於HTTP/1.1服務器至少應該事先GET和HEAD方法,而其它的方法都是可選的;


(3)HTTP請求的基本格式(重要)

格式如下:

< request-line >

< headers >

< blank line >

{ < request-body > }   

 

格式代碼說明見如下表格:

請求內容 說明解析
<request-line>

第一行必須是一個請求行(request line),說明請求的類型、要訪問的資源以及使用的HTTP版本,這些內容之間用空格來分隔。例如:

GET / HTTP/1.1

<headers>

接着的這個是標頭的部分,說明服務器要使用的附加信息,這部分一般是由多行組成。

<blank line> 然後在標頭之後是一個空行(blank line),它表示的標頭的結束位置。而這個空行是必須要存在的無論前後的內容如何,即使不存在請求體的部分,這個空行也是必須要存在的。
<request-body> 空行之後是請求的主體(request-body),主體中可以包含任意的數據。

 

 

 

 

 

 

 

注意:1. 請求行和標頭必須以回車換行(<CR><LF>)作爲結尾。空行內必須只有<CR><LF>而無其他空格;

           2. 在HTTP/1.1中,標頭中必須有Host部分,其他都是可選的;

           3. 即使不存在請求體的部分,這個空行也是必須要存在的;

 

※這裏稍微提一下<CR><LF>的含義和來源:

CR是Carriage Return的英文的縮寫,意思是"回車",我們通常用" \r "來表示。

LF是Line Feed的英文縮寫,意思是"換行",我們通常用" \n "來表示。

在Windows系統中用" \r\n "表示下一行,而在MAC系統中則是用" \r "表示下一行,在 Unix系統中是用" \n "表示下一行,所以上面說的是在Windows下用回車換行(<CR><LF>)作爲結尾。


這裏我們平時些程序的時候,最常用到的是GET請求和POST請求,我們就以這兩個請求爲列子,探究一下請求體的格式:

(4)GET請求的請求體舉例

我們在百度的頁面中輸入1,然後點擊"百度一下"。在Chrome的控制檯中可以看到如下的內容,如圖:

GET /s?ie=utf-8&f=8&...&inputT=533 HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: <...>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: https://www.baidu.com/?tn=02003390_15_hao_pg
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: <...>

我把一些不重要的內容進行了省略化,我們重點分析一下重要的幾行,如下分析表格:

重要行 解析
第一行 (GET起始行)

這一行是由3個部分組成的,分別是"GET"、"/s?name1=value1&...&nameN=valueN"和"HTTP/1.1"組成。

【1】其中"GET"是說明請求的類型是GET請求;

【2】而" /s?name1=value1&...&nameN=valueN "部分,在" ? "之前的部分是URL地址,即Host加上"?"之前的部分,即爲 " www,baidu.com/s ",如果是單純一個" / "就表示的是網址下的根目錄" www.baidu.com/ ",對於" ? "之後的部分,則是GET請求的參數,每一個參數之間通過" & "分隔,其格式如下:

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

這一條信息被稱爲查詢字符串(Query String);

【3】最後的" HTTP/1.1 "說明使用的HTTP協議版本是1.1版本;

第二行 (Host起始行)

第二行是Host標頭,指出請求的目的地址。結合上面第一行的第二部分使用。

注意:上面已經說過HTTP1.1才需要使用標頭Host,而1.0的版本是不需要的;

第三行(Connenction起始行) 第三行是Connection標頭,通常將瀏覽器操作設置爲Keep-Alive(當然也可以是其他的值)。
第四行(User-Agent起始行) 第四行是User-Agent標頭,服務器和客戶端腳本都能夠訪問它,它是瀏覽器類型檢測邏輯的重要基礎。該信息由使用的瀏覽器來定義,並且在每個請求中都會自動發送。
最後空行

這一行在上面的圖中並沒有標出,但是按照上面的格式,這一行是存在的,表示標頭的結束。

注意:上面已經說過即使不存在請求體的部分,這個空行也是必須要存在的。

 

 

 

 

 

 

 

 

 

 

 

 

 


(5)POST請求體舉例

我們來使用一下百度翻譯,翻譯"烏龍茶",獲得請求體如下圖所示:

可以看到其中不但有請求的標頭,還有表單數據。我將上面的數據整理如下:

Request Header:

POST /langdetect HTTP/1.1
Host: fanyi.baidu.com
Connection: keep-alive
Content-Length: 33
Accept: */*
Origin: https://fanyi.baidu.com
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: https://fanyi.baidu.com/?aldtype=16047
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: <...>


Form Data:

query=%E4%B9%8C%E9%BE%99%E8%8C%B6

我把一些不重要的內容進行了省略化,我們重點分析一下重要的幾行,如下分析表格:

重要行 解析
第一行(GET起始行)

【1】第一行的第一部分請求類型修改爲了POST請求;

【2】第二部分僅僅只含有URL,而不再含有" ? ",以及" ? "之後的參數部分,這部分消失的參數將會出現的請求體的表單部分中;

我們可以看到請求的地址爲 "fanyi.baidu.com/langdetect "

第二行(Host起始行)、第三行(Connection起始行)、第八行(User-Agent起始行) 和上面的GET請求的標頭作用一致
第四行(Content-Length起始行) 這一行的Content-Length標頭說明了請求主體的字節數
第九行(Content-Type起始行) 第九航的Content-Type標頭

 

 

 

 

 

 

 

 

 


(6)HTTP響應的基本格式(重要)

格式如下:

< status-line >

< headers >

< blank line >

{ < response-body > }   

格式代碼說明見如下表格:

響應內容 解析說明
< status-line > 第一行都會是一個狀態行,該行的內容一次是當前的HTTP版本號、3位數字組成的狀態碼以及描述這個狀態的短語組成,每個組成部分用空格分隔
< headers >、< blank line >和{ < response-body > }  之後的部分個請求體格式中的差別不大

 

 

 

 

 


(7)HTTP狀態碼分類及常用狀態碼(重要)

 

【1】狀態碼以第一個數字代表當前響應的類型,具體的規定如下表:

狀態碼 大類含義 解釋
1XX 消息 請求已經被服務器接收,繼續處理
2XX 成功 請求已經成功被服務器接收、理解並接收
3XX 重定向 需要後續操作才能完成這一請求
4XX 請求錯誤 請求含有詞法錯誤或者無法被執行
5XX 服務器錯誤 服務器在處理某個正確請求的時候發生錯誤

 

 

 

 

 

 


【2】HTTP常用的狀態碼

狀態碼 含義 說明
200 OK 找到了資源,並且一切正常
304 NOT MODIFIED 該資源在上次請求之後沒有任何修改(這通常用於瀏覽器的緩存機制)
401 UNAUTHORIZED 客戶端無權訪問該資源(這通常會使得瀏覽器要求用戶輸入用戶名和密碼,以登錄到服務器)
403 FORBIDDEN 客戶端未能獲得授權(這通常是在401之後輸入了不正確的用戶名或密碼)
404 NOT FOUND 在指定的位置不存在所申請的資源
405 METHOD NOT ALLOWED 不支持對應的請求方法
501 NOT IMPLEMEMTED 服務器不能識別請求或者未實現指定的請求

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章