天天看點

Http協定詳解

http(hypertext transfer protocol)就是超文本傳輸協定,它是現代網際網路最重要也是最基本的協定。http協定是無狀态的、應用層協定,它是web開發的基礎,如果想從事web方面的開發,一定要仔細學習一下這個協定。

http設計的目的就是支援用戶端(一般是浏覽器)和伺服器端進行友善的溝通,它是一個b/s協定。因為在網際網路中,一個伺服器往往需要處理大量的用戶端請求,http協定應該盡可能少的占用系統資源。 為了達到這個目的,http協定被設計成無狀态的。http協定是在tcp/ip之上的一種協定(http屬于應用層,tcp/ip屬于運輸層),預設端口采用的是80。

http協定棧:

Http協定詳解

我們把http協定中通信的兩方稱作client和server(或host),client向server端經過http協定發送一個request,server端收到request後經過一些列的處理傳回client一個response,整個過程如下圖所示:

Http協定詳解

我們現在用到的版本是http/1.1,它比1.0版本添加了更多特性。其中比較重要的特性有:

在詳細介紹http協定之前我們先看一下url。對于url我想大家都已經很熟悉了,我們如果通路一個網站,我們不需要了解http協定,我們隻需要在浏覽器中輸入這個網站的url即可。web傳輸的核心就是請求消息,而請求消息就是通過url進行定義的。 url(uniform resource locator) 位址用于描述一個網絡上的資源,基本格式如下:

Http協定詳解

scheme:指定低層使用的協定,一般是http,如果強調安全的話可以是http

host:http伺服器的ip位址或者域名

port:http伺服器的預設端口是<code>80</code>,這種情況下端口号可以省略。如果使用了别的端口,必須指明

path:通路資源的路徑

url-params:url的參數

query-string:發送給http伺服器的資料

anchor:錨

當你在浏覽器輸入url<code>http://www.website.com</code>的時候,浏覽器發送一個request去擷取<code>http://www.website.com</code>的html。伺服器把response發送回給浏覽器。浏覽器分析response中的 html,發現其中引用了很多其他檔案,比如圖檔,css檔案,js檔案。

浏覽器會自動再次發送request去擷取圖檔,css檔案,或者js檔案。當所有的檔案都下載下傳成功後, 網頁就被顯示出來了。

我們通過url告訴了浏覽器我們去哪個網站(主機)獲得資源,而我們要在這個網站上做什麼操作呢?這個具體的操作就是由請求method定義的。當然,用戶端可以對伺服器做多種類型的操作,為此<code>http1.1</code>協定共定義了八種标準操作:

get:向指定的資源發出“顯示”請求。使用get方法應該隻用在讀取資料,而不應當被用于産生“副作用”的操作中,例如在web application中。其中一個原因是get可能會被網絡蜘蛛等随意通路。

post:向指定資源送出資料,請求伺服器進行處理(例如送出表單或者上傳檔案)。資料被包含在請求本文中。這個請求可能會建立新的資源或修改現有資源,或二者皆有。

put:向指定資源位置上傳其最新内容。

delete:請求伺服器删除request-uri所辨別的資源。

options:這個方法可使伺服器傳回該資源所支援的所有http請求方法。用’*’來代替資源名稱,向web伺服器發送options請求,可以測試伺服器功能是否正常運作。

head:與get方法一樣,都是向伺服器發出指定資源的請求。隻不過伺服器将不傳回資源的本文部分。它的好處在于,使用這個方法可以在不必傳輸全部内容的情況下,就可以擷取其中“關于該資源的資訊”(元資訊或稱中繼資料)。

trace:回顯伺服器收到的請求,主要用于測試或診斷。

connect:<code>http/1.1</code>協定中預留給能夠将連接配接改為管道方式的代理伺服器。通常用于ssl加密伺服器的連結(經由非加密的http代理伺服器)。

method名稱是區分大小寫的。當某個請求所針對的資源不支援對應的請求方法的時候,伺服器應當傳回狀态碼<code>405(method not allowed)</code>,當伺服器不認識或者不支援對應的請求方法的時候,應當傳回狀态碼<code>501(not implemented)</code>。

其中的get、post、put、delete這四種method分别對應者對遠端服務資源的增、删、改、查操作,而其中最長用的是get和post。

get請求的資料會附在url之後(就是據放置在http協定頭中),以“?”分割url輸資料,多個參數用“&amp;”連接配接;例如:<code>login.action?name=tom&amp;password=securiy</code>。

post會把送出的資料放置在是http包的正文中。上文示例中<code>name=professional&amp;id=11101</code>就是實際的傳輸資料;

http協定沒有對傳輸的資料和url長度進行限制, 但特定浏覽器和伺服器對url長度有限制, 是以對于get送出時,傳輸資料就會受到url長度的限制; 由于post操作不是通過url傳值,理論上資料長度不受限。

post的安全性要比get的安全性高,通過get送出資料,使用者名和密碼将明文出現在url上,容易被他人看到,url資訊也可能會被記錄到曆史紀錄中。

get執行個體:

post 執行個體:

通過url和method,用戶端就可以發送一個完整的請求給服務端。當然服務端也會做出響應。狀态碼就是非常重要的一種響應,用戶端通過狀态碼就可以了解服務端做出何種響應。<code>http/1.1</code>中定義了5類狀态碼, 狀态碼由三位數字組成,第一個數字定義了響應的類别:

1xx 提示資訊; 表示請求已被成功接收,告訴用戶端可以繼續發送下一個請求了,若如果已發送完畢可以忽略它。

2xx 成功

3xx 重定向; 要完成請求必須進行更進一步的處理

4xx 用戶端錯誤;請求有文法錯誤或請求無法實作

5xx 伺服器端錯誤;伺服器未能實作合法的請求

最常見的response處理成功之後傳回的狀态碼:

http/1.1 200 ok (crlf)

至此,我們已經了解到了url、verb、status code相關概念,而這些資訊就是組成http消息體的主要資訊,下面我們就具體看一下http消息體的具體結構。

Http協定詳解

http消息分為request和response兩種消息,http協定對這兩種消息定義了如下結構:

從上面定義我們可以看到,http的request和response消息都是由三部分組成:

對于start-line,又分為:

對于headers則有如下幾種:

下面我們再用兩幅圖具體看一下request和response的消息格式:

request消息格式定義:

Http協定詳解

response消息格式定義:

Http協定詳解

通過上面介紹我們已經http消息的headers共分為三種,分别是<code>general headers</code>、<code>entity headers</code>、<code>request/response headers</code>。

我把被request和response共享的headers成為general headers,具體有:

cache -control指定請求和響應遵循的緩存機制。

connection 允許用戶端和伺服器指定與請求/響應連接配接有關的選項

date 提供日期和時間标志,說明封包是什麼時間建立的

pragma頭域用來包含實作特定的指令,最常用的是pragma:no-cache

trailer 如果封包采用了分塊傳輸編碼(chunked transfer encoding) 方式,就可以用這個首部列出位于封包拖挂(trailer)部分的首部集合

transfer-encoding 告知接收端為了保證封包的可靠傳輸,對封包采用了什麼編碼方式

upgrade 給出了發送端可能想要”更新”使用的新版本和協定

via 顯示了封包經過的中間節點(代理,網嘎un)

entityheaders主要用來描述消息體(message body)的一些元資訊,具體有:

其中,以content為字首的headers主要描述了消息體的結構、大小、編碼等資訊,expires描述了entity的過期時間,last-modified描述了消息的最後修改時間。

這部分内容放在下面的request消息體和response消息體中介紹。

通過上面介紹,我們對request消息體結構已經有了大體了解,本節我們再深入介紹一下。

request-line是request消息體的第一部分,其具體定義如下:

其中<code>sp</code>代碼字段的分隔符,<code>http-version</code>一般就是<code>"http/1.1"</code>,後面緊接着是一個<code>換行</code>。

在<code>request-line</code>後面緊跟着的就是<code>headers</code>。我們在上面已經介紹了<code>general headers</code>和<code>entity headers</code>,下面便是<code>request headers</code>定義:

<code>request headers</code>扮演的角色其實就是一個request消息的調節器。需要注意的是若一個headers名稱不在上面清單中,則預設當做<code>entity headers</code>的字段。

字首為<code>accept</code> 的headers定義了用戶端可以接受的媒介類型、語言和字元集等。<code>from</code>, <code>host</code>, <code>referer</code> 和<code>user-agent</code> 詳細定義了用戶端如何初始化request。字首為<code>if</code> 的headers規定了伺服器隻能傳回符合這些描述的資源,若不符合, 則會傳回<code>304 not modified</code>。

若<code>request-line</code>中的<code>method</code>為<code>get</code>,請求中不包含消息體,若為<code>post</code>,則會包含消息體。

response消息格式和request類似,也分為三部分:<code>response-line</code>、<code>response headers</code>、<code>response body</code>。

response-line具體定義如下:

<code>http-version</code>字段值一般為<code>http/1.1</code>

<code>status-code</code>前面已經讨論過了

<code>reason-phrase</code> 是對<code>status code</code>的具體描述

一個最常見的response響應為:

http/1.1 200 ok

下面是<code>response-header</code>的定義:

<code>age</code> 表示消息自server生成到現在的時長,機關是秒

<code>etag</code> 是對entity進行md5 hash運算的值,用來檢測更改

<code>location</code> 被重定向的url

<code>server</code> 伺服器辨別

參考資料:

<a href="http://code.tutsplus.com/tutorials/http-the-protocol-every-web-developer-must-know-part-1--net-31177">http://code.tutsplus.com/tutorials/http-the-protocol-every-web-developer-must-know-part-1–net-31177</a>

<a href="https://zh.wikipedia.org/wiki/%e8%b6%85%e6%96%87%e6%9c%ac%e4%bc%a0%e8%be%93%e5%8d%8f%e8%ae%ae">https://zh.wikipedia.org/wiki/%e8%b6%85%e6%96%87%e6%9c%ac%e4%bc%a0%e8%be%93%e5%8d%8f%e8%ae%ae</a>