這裏整理一下關於Http協議的學習筆記。html
注:文章中的部分圖片來自於網絡,侵刪java
大學學過計算機網絡課的都知道OSI模型,即計算機網絡模型,OSI模型由7層組成,除了OSI模型還有網絡協議棧(也稱爲TCP/IP模型),其表示以下圖(圖片來自網絡)所示:linux
通常咱們都使用五層模型的概念,這裏就以五層模型來總結一下各個層的功能。web
五層模型在實際中的通訊過程以下所示:面試
下面一圖囊括了大部分的各層協議:chrome
在linux上的進程通訊學習文章中介紹了套接字的使用,主要用於進行遠程進程之間的通訊,在計算機網絡知識領域,套接做爲進程與網絡之間溝通的媒介提供了應用層與傳輸層連接的功能。在應用程序中咱們經過將在應用層封裝好的報文交付於套接字使得網絡進程之間能夠進行相互的通訊。既然進行通訊,就要商量好對應的協議,應用層協議就定義了應用程序進程中如何進行傳遞報文的。數據庫
應用層協議定義了以下的規則:瀏覽器
關於應用層協議能夠查看RFC文檔來了解對應詳細規則。緩存
Http(超文本傳輸協議)是互聯網上應用最爲普遍的一種網絡協議。全部的WWW文件都必須遵照這個標準。Http協議使用TCP協議做爲傳輸層的支撐,保證了在傳輸過程當中的可靠性,可是,Http也是一個無狀態的協議,即一個請求對應一次響應,服務器只響應客戶端的請求,不記錄任何狀態信息,一秒內發送2次相同的請求,服務器就會響應2次。服務器
當使用TCP的時候,TCP提供了兩種鏈接的方式:非持續性鏈接以及持續性鏈接(默認),區別在於每一個請求/響應是單獨的一個TCP鏈接發送仍是全部的請求都由一個TCP鏈接發送。
Http報文分爲兩種:請求報文和響應報文。請求報文的結構以下:
首先查看一個簡單的請求報文:
GET /dir/page.html HTTP/1.1 Host: www/baidu.com Connection: close User-Agent: Mozilla/5.0 Accept-language: fr
報文的第一行稱之爲請求行,後續的稱之爲首部行(請求頭部)。請求行包含三個字段,分別是方法字段,URL字段以及Http版本字段。
關於方法字段,HTTP1.0定義了三種請求方法: GET, POST 和 HEAD方法。HTTP1.1新增了五種請求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。下面是各個方法的意義(圖片截圖來自菜鳥教程):
Http中定義了大量的請求頭部以及響應頭部,詳細的能夠查看這篇文章,這裏就不詳細羅列出來了。從上面的圖中還能夠看到最後一行爲請求數據(請求實體),請求實體在POST中會進行填充數據,如表單數據。
接下來看下響應報文,響應報文的結構與消息報文的結構一致,惟一不一樣的是叫法,第一行爲狀態行,而後是響應行(狀態行),響應頭部,空行和響應正文。看下例子:
HTTP/1.1 200 OK Date: Mon, 27 Jul 2009 12:28:53 GMT Server: Apache Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT ETag: "34aa387-d-1568eb00" Accept-Ranges: bytes Content-Length: 51 Content-Type: text/plain
關於Http響應狀態碼介紹以下:
羅列一些例子以下:
在Http使用中,我以爲須要注意的是兩點,一個cookie的使用,另外一個是Http的緩存機制。下面對兩方面的知識作個整理。
首先是cookie,上述也介紹了Http是一個無狀態的,所以也簡化了服務器的設計。然而從用戶的角度而言,用戶更傾向於保存在某個網站上保存必定的信息,如用戶信息(chrome上會常常看到提示咱們是否保存用戶信息),這時候cookie就應運而生了。HTTP Cookie(也叫Web Cookie或瀏覽器Cookie)是服務器發送到用戶瀏覽器並保存在本地的一小塊數據,它會在瀏覽器下次向同一服務器再發起請求時被攜帶併發送到服務器上。一般,它用於告知服務端兩個請求是否來自同一瀏覽器,如保持用戶的登陸狀態。Cookie使基於無狀態的HTTP協議記錄穩定的狀態信息成爲了可能。
一次完整的cookie使用記錄以下,更詳細的能夠查閱這篇文章:
接下來就是Http緩存操做,首先自主思考一下若是咱們須要本身實現該怎麼作呢?
既然咱們能想到,開發Http協議的人可能比咱們更厲害咯,下面總結一下這兩種緩存方式對應Http的實現。
首先是Expires(對應第一種緩存狀況)以及Pragma,Expires,Pragma都是Http1.0的產物,Pragma主要控制是否容許客戶端緩存,若是服務器返回了:
Pragma: no-cache
那麼就是告訴客戶端禁止緩存,每次數據都從服務器去拿。Expires字段來自響應實體,服務器在返回數據時候能夠加上當前字段來設置緩存時間,如底下返回數據:
Expires: Wed, 21 Oct 2015 07:28:00 GMT
Expires返回一個GMT標準時間,客戶端獲取以後存入數據庫,在緩存時間內使用緩存,不然再次請求服務器。若是Expires,Pragma一塊兒返回,Pragma的優先級高於Expires,即客戶端不容許緩存。
響應報文中Expires所定義的緩存時間是相對服務器上的時間而言的,其定義的是資源「失效時刻」,若是客戶端上的時間跟服務器上的時間不一致(特別是用戶修改了本身電腦的系統時間),那緩存時間可能就沒啥意義了。
接着介紹一下Cache-Control,Cache-Control在Http1.1中實現。Cache-Control的請求實體可選參數以下:
響應實體可選參數以下:
Cache-Control配合其餘關鍵字能實現咱們上面說的任何一種緩存方式。這邊咱們說的對應於響應實體Cache-Control,由於相對於客戶端開發而言,客戶端對於服務端的緩存策略控制相對叫弱。Cache-Control中經過max-age也實現了Expires的功能,不一樣的是,max-age返回的是時間值,而不是明確的時間,如:
Cache-Control: max-age=36000
因爲返回的是時間值,就能夠趨避客戶端時間與服務器時間相差較大的狀況,從而解決了Expires的侷限性。與Pragma對應的是no-store參數。
對比緩存實現主要有兩種途徑:Last-Modified/If-Modified-Since以及Etag/If-None-Match方式。
使用Last-Modified/If-Modified-Since方式的流程圖以下:
Last-Modified主要回傳的是對應文件服務器端最後修改的時間,客戶端在第二次調用時將Last-Modified得到到的value存放在If-Modified-Since中從新傳給服務端,服務端作數據比對,並返回對應的狀態碼給客戶端,若是返回304,表明服務器數據未更新,直接使用客戶端維護的緩存便可;更新了,返回200並帶上數據發送給客戶端。
經過Last-Modified也有必定的侷限,若是一個文件更新了可是其內容本質上不變,那麼服務器也會認爲客戶端須要進行更新數據,從而返回服務器認爲更新後的,可是實際上沒有更新的數據,這樣形成了客戶端從新得到一個如出一轍的文件。
因爲Last-Modified的侷限性,所以引入了Etag參數,Etag表明了文件的惟一標識碼(如md5),Etag和If-None-Match一同使用,使用的流程以下圖:
流程跟Last-Modified/If-Modified-Since一致。
總結一下相關關鍵字調用的優先級:
Pragma -> Cache-Control (max-age>Etag>Last-Modified)-> Expires
放上一張緩存流程圖:
這裏總結一下一題面試題吧,敘述一下在瀏覽器中輸入http://www.baidu.com後發生的狀況:
參考資料
<<計算機網絡-自頂向下方法>>
http://www.cnblogs.com/Joans/p/3956490.html
http://www.javashuo.com/article/p-urqfeegv-ec.html