計算機網絡學習整理:Http協議

這裏整理一下關於Http協議的學習筆記。html

注:文章中的部分圖片來自於網絡,侵刪java


TCP/IP五層模型

大學學過計算機網絡課的都知道OSI模型,即計算機網絡模型,OSI模型由7層組成,除了OSI模型還有網絡協議棧(也稱爲TCP/IP模型),其表示以下圖(圖片來自網絡)所示:linux

通常咱們都使用五層模型的概念,這裏就以五層模型來總結一下各個層的功能。web

  • 應用層:網絡應用程序以及對應應用層協議存放的地方,常見如Http,SMTP以及FTP等協議。在兩個應用程序進行網絡交互的時候,應用層對應生成/獲取到的信息分組稱之爲報文
  • 運輸層:負責爲端和端提供應用程序進程間的數據傳輸服務,這一層包含兩個傳輸協議,傳輸控制協議即TCP和用戶數據報協議UDP。TCP提供了可靠的面向鏈接的服務,使用TCP協議能夠確保傳遞以及流量控制,而且提供擁塞控制。而UDP則提供無鏈接服務,不可靠,沒有流量控制,也沒用擁塞控制,單純傳遞數據,不保證是否到達對應端。運輸層封裝的數據稱之爲報文段,報文段主要是將應用層的報文數據加上運輸層生成的信息(如端口號)。
  • 網絡層:網絡層封裝的數據稱之爲數據報,其主要包含運輸層傳遞過來的報文段以及對應IP地址信息。
  • 鏈路層:網絡層的數據報封裝成合適在物理網絡上傳輸的格式並傳輸,或將從物理網絡接收到的幀解封,取出IP數據報交給網絡層。因特網的網絡層經過一系列路由器在源和目的地之間發送分組。爲了將分組從一個節點(主機或路由器)移動到路徑上的下一個節點,網絡層必須依靠鏈路層的服務。鏈路層協議主要有以太網,WiFi以及電纜接入網的DOCSIS協議等。
  • 物理層:物理層負責將鏈路層傳遞過來的幀轉化爲一個一個比特進行傳輸。該層協議仍然與鏈路層相關,而且進一步與該鏈路(如單模光纖,雙絞銅線等)的實際傳輸媒體掛鉤

五層模型在實際中的通訊過程以下所示:面試

下面一圖囊括了大部分的各層協議:chrome


應用層協議介紹

linux上的進程通訊學習文章中介紹了套接字的使用,主要用於進行遠程進程之間的通訊,在計算機網絡知識領域,套接做爲進程與網絡之間溝通的媒介提供了應用層與傳輸層連接的功能。在應用程序中咱們經過將在應用層封裝好的報文交付於套接字使得網絡進程之間能夠進行相互的通訊。既然進行通訊,就要商量好對應的協議,應用層協議就定義了應用程序進程中如何進行傳遞報文的。數據庫

應用層協議定義了以下的規則:瀏覽器

  • 交換報文的類型,例如請求報文以及響應報文。
  • 各個報文類型的語法,如報文中各個字段以及字段描述。
  • 字段的語義。
  • 一個進程什麼時候以及如何發送報文,接受報文的規則。

關於應用層協議能夠查看RFC文檔來了解對應詳細規則。緩存


Http協議

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緩存操做,首先自主思考一下若是咱們須要本身實現該怎麼作呢?

  • 首先考慮一種狀況,服務器的數據永遠是不變的(某張具體的jpg),那麼咱們就能夠在服務器返回字段的時候標明這個數據不會變,客戶端在第二次請求的時候發現有緩存,直接使用就能夠了。一樣的弱可變性也能這麼實現。好比我一張圖片一個月後過時,那麼服務器告訴客戶端一個月後過時就能夠了。(強制緩存)
  • 其次可能存在另外一種狀況,服務器的數據是可變的,這時候怎麼辦呢?能夠這麼作,假設咱們在獲取一個文件,服務器返回文件的時候把文件的md5告訴咱們,客戶端把值存下來,在客戶端第二次請求的時候,咱們把md5傳過去,服務器把md5跟最新的文件的md5作比對,若是相同,返回一個相同的字段給客戶端,客戶端直接使用本地緩存便可;若是不相同,那麼服務器再把文件以及md5返回給客戶端。(對比緩存)

既然咱們能想到,開發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後發生的狀況:

  1. 判斷本地是否有緩存,若是是強制緩存,則直接返回緩存數據,請求執行結束,若是是對比緩存,則向服務端在請求體中添加參數If-None-Match/If-Modified-Since。
  2. DNS解析域名獲取目標IP地址。
  3. 進行TCP三次握手過程,確認鏈接。
  4. 服務端發送數據,進行四次握手,一次請求結束。

參考資料

https://baike.baidu.com/item/%E4%BA%94%E5%B1%82%E5%9B%A0%E7%89%B9%E7%BD%91%E5%8D%8F%E8%AE%AE%E6%A0%88/8353884?fr=aladdin

<<計算機網絡-自頂向下方法>>

http://www.cnblogs.com/Joans/p/3956490.html

http://www.javashuo.com/article/p-urqfeegv-ec.html

http://www.javashuo.com/article/p-drsaueus-ck.html

http://imweb.io/topic/5795dcb6fb312541492eda8c

相關文章
相關標籤/搜索