計算機網絡——HTTP協議詳解


一、前言

  前段時間為了研究計算機網絡,看了看《計算機網絡自頂向下方法》這本書。不得不說這真是一本好書,內容詳細,而且講解的淺顯易懂,采用了大量類比的方式進行講解,而不是單純的敘述理論,同時在每一章的后面都有大量的練習題以及很有意思的編程題,所以開頭先來推薦一波。這本書我暫時只看到了第二章,剛看完HTTP的內容,所以寫一篇HTTP相關的博客,就當是記筆記了。


二、詳解

 2.1 HTTP概述

  HTTP是一個應用層的協議,全稱是超文本傳輸協議,它是web的核心。HTTP由兩個程序實現——客戶端程序和服務端程序,而HTTP的作用簡單來說就是客戶端向服務器發請求,而服務器根據請求做出響應HTTP定義了Web客戶端向服務器請求資源的方式,以及Web服務器向客戶端回送資源的方式,也就是HTTP請求+響應模型。客戶端向服務器發送請求報文請求資源,服務器接收到請求,向客戶端回送包含這些資源的響應報文。

  HTTP基於TCP協議,由TCP協議支持數據的傳輸,這說明HTTP協議是一個面向連接的可靠協議。當客戶端向服務器請求資源時,首先將與服務器建立一個TCP連接,當TCP連接建立成功時,客戶端和服務器之間就可以通過套接字接口訪問TCP,客戶端通過TCP連接傳輸請求報文,而服務器也通過這個TCP連接回送響應報文及資源。由於TCP的可靠傳輸,保證了HTTP的報文一定能夠完整的送到服務器上,而服務器的響應也能完整的回送到客戶。

  HTTP請求的資源一般是一個Web頁面,而一個Web頁面是由一個或多個對象組成的,這個對象可能是一個html文件,一張圖片,甚至是一段視頻或者小程序。對於HTTP來說,組成一個Web頁面的這些對象並不屬於同一個資源,每一個對象都是一個單獨的資源,需要逐一請求。假設我們向服務器請求一個Web頁面,這個頁面由一個html文件以及5張圖片組成(html通過路徑引用圖片),則這個頁面共有6個對象,當服務器接收到客戶端對頁面的請求后,將html文件通過響應報文返回,而客戶端接收到響應的html文件后,發現它還引用了5張圖片,這時客戶端將再次發送5HTTP請求,來分別請求這5張圖片。

  服務器向客戶端發送被請求的文件,但是不記錄任何客戶的信息,所以當你連續向服務器請求同一份資源兩次時,服務器也會給你響應兩次,不會因為你已經請求過就不給你響應了。正是因為HTTP不記錄客戶的信息,所以它也是一個無狀態協議


 2.2 非持續連接和持續連接的HTTP

  大多數情況下,我們對Web服務器發出請求時,都不止發出一個請求,比如上面說到的包含5張圖片的頁面。那這個時候就需要考慮一個問題,對於這多次目的地相同的請求/響應,HTTP是對每一個請求/響應使用同一個TCP連接,還是每次請求單獨創建一個TCP連接呢?這里就分兩種情況,多次請求/響應使用同一個TCP連接的被稱為持續連接,而每個請求/響應單獨使用一個TCP連接,則被稱為非持續連接。而HTTP默認使用的是持續連接,但是也可以通過配置,改用非持續連接。下面就來簡單說一說兩者的區別。

  (1)非持續連接

  非持續連接表示對於每一個請求/響應,都將單獨建立一個TCP連接來進行。假設我們還是以之前說過的例子來講解:我們向服務器請求一個包含5張圖片的頁面,而頁面的路徑假設就是HTTP://www.tewuyiang.cn/index.html(這是我的個人服務器,目前部署了一個制作簡單的小游戲),當我們請求這個路徑時,將發生以下情況:

  1. HTTP客戶進程通過80端口向服務器www.tewuyiang.cn發起一個TCP連接,80端口時HTTP的默認端口;
  2. HTTP客戶進程通過套接字向服務器發送一個請求報文,請求資源的路徑為/index.html
  3. HTTP服務器進程通過套接字接收到該請求,從它的存儲器(如:RAM)中搜索HTTP://www.tewuyiang.cn/index.html這個資源,生成一份響應報文,並將html頁面封裝進響應報文中,並通過套接字將此報文回送給客戶端;
  4. HTTP服務器通知TCP斷開連接(但是直到TCP確認客戶端已經接收到完整的報文后,才會將連接斷開);
  5. HTTP客戶進程完整的接收到響應報文好,TCP連接斷開。客戶端解析響應報文后,發現封裝的對象是一個html文件,且html文件包含5張圖片的引用;
  6. 重復上面步驟1-4,請求頁面包含的5張圖片;

  非持續連接的缺點很明顯,那就是對於每一個請求/響應都需要建立TCP連接,這樣將導致服務器需要維護的連接大大增加,比如一個頁面包含10張圖片,那總共就得2建立11給連接,這樣將給服務器造成巨大的壓力。而好處就是,多個連接可以同時建立(一個瀏覽器一般可以同時建立5-10個連接),表示有多個通道,通道之間傳輸數據是並行的,多個請求/響應可以同時進行,這樣就不會造成排隊的情況,效率較高。

  (2)持續連接

  持續連接表示某個客戶端與一個服務器建立連接后,在一段時間內,向服務器發送的請求以及服務器發送的響應,都可以通過這一條連接來進行。這個應該很好理解。而持續連接也分為兩種:

  1. 不帶流水線的持續連接:這表示一次性只能進行一個請求/響應,而下一個必須得等上一次完成后才進行;
  2. 帶流水線的持續連接:這表示對對象的請求可以一個個發出,而不需要等未完成的請求結束(但不是完全並行);

  對於長時間未使用的連接,HTTP會將它關閉,而這個超時時間也可以進行配置。

  持續連接的好處也很明顯,那就是節省資源,多個請求共用一個連接;但是缺點就是效率可能相對要低一些。HTTP的默認模式就是帶流水線的持續連接


 2.3 HTTP報文格式

  接下來,我們就來談一談HTTP協議的報文格式吧。HTTP的報文分為請求報文和響應報文。

  (1)請求報文

  下面是一段我從瀏覽器截取下來的HTTP的請求報文,請求的資源是一張圖片:

  HTTP請求報文的第一行為請求行,剩下的都叫首部行,下面我來一行一行解釋上面的內容:

  首先是第一行,也就是請求行,它包含三部分內容:請求方法,資源路徑,HTTP協議版本,它們三者由空格隔開。第一部分的請求方法表示客戶端向瀏覽器發送的請求的類別,我們常用的請求方式是GETPOST請求:

  • GET:向服務器請求資源,服務器將請求的資源返回;
  • POST:向服務器提交數據並請求處理(比如說提交表單),數據被包含在請求體中。POST 請求可能會導致新的資源的建立和/或已有資源的修改;

  上面兩個請求方式都是HTTP1.0中定義的,而HTTP1.0除了上面兩個請求方法,還有一個HEAD請求:

  • HEAD:類似於 GET 請求,只不過返回的響應中沒有具體的內容,用於獲取報頭;

  在HTTP1.1中,又新增了六種請求,分別是OPTIONSPUTPATCHDELETETRACECONNECT 方法,它們的定義我就不一個個列出來了,大家可以點擊后面的連接查閱——HTTP請求方法

  緊隨請求方法之后的是資源在HTTP服務器上的路徑,報文中的路徑是/img/prop3.png,表示我們請求的是HTTP服務器路徑下,img文件夾下的prop3.png這張圖片。這之后的HTTP1.1表示的就是這次請求使用的HTTP的版本了。

  請求行下面的都是首部行,而首部行都是name: value格式的,name表示這個首部的名字,而value就是首部的具體值了。第一個首部行的名字叫Host,表示的是HTTP服務器所在的地址,而這里的地址是www.tewuyiang.cn。第二個首部行的名字是Connection,這個表示的就是我們上面提到的HTTP的連接類型了,而它的值是keep-alive,就是告訴服務器,使用的是持續連接,若值為close,表示的就是非持續連接。第三個首部行User-Agent的作用就是指明用戶代理,也就是告訴服務器,發送這次HTTP請求的瀏覽器的類型。第四個首部行Accept的作用告訴服務器自己希望接收的資源的類型,若服務器響應的資源與此不一致,將會報錯,而從上面的報文中可以看出,這個請求希望受到一張圖片。Referer的作用是用來防止惡意請求,提高訪問資源的安全性。Accept-Encoding的作用是告知服務器,當前瀏覽器支持的編碼類型。Accept-Language的作用是告知HTTP服務器客戶端想要獲取資源的語言版本,若服務器中不包含此語言版本,則將回送默認版本。

  下面這張圖是HTTP請求報文的標准格式:


  (2)響應報文

  同樣,我們先來看一段響應報文:

  響應報文的第一段由兩部分組成,分別是HTTP版本以及狀態碼,上面的報文中,HTTP的版本為1.1,與請求的版本相同,之后緊跟的狀態碼為200,這是最常見的狀態碼,表示請求成功。若還想知道其他狀態碼,可以點擊菜鳥教程查閱,這里列出常見的四種:

  • 200 - 請求成功;
  • 301 - 資源(網頁等)被永久轉移到其它URL;
  • 404 - 請求的資源(網頁等)不存在;
  • 500 - 內部服務器錯誤;

  第一行之后的這些行,被稱為首部行,與請求報文中的首部行類似,也是name: value。第一個首部行的名稱叫做Accept-Ranges,它的作用是告知客戶端,此資源是否支持范圍請求,而范圍請求可以支持斷點續傳多線程分片下載bytes表示支持,而none表示不支持。Last-Modified的作用后面說緩存時單獨拿出來說。Content-type的作用就是標識資源的類型,這里image/png表示資源是一張圖片。Content-Length表示資源的字節數,圖片中的值是8729,表示這張圖片共有8729個字節。最后一個Date的作用就是表示服務器發送該響應報文的日期時間。

  下面這一張是HTTP響應報文的標准格式,可以看到,在最后面還有一個叫實體體的部分,這里就是用來放服務器回送的資源的,例如請求的圖片。


 2.4 Web緩存器

  Web緩存器也叫代理服務器,它在某些情況下可以代替HTTP服務器滿足客戶的需求。Web緩存器有自己的存儲空間,並保存有最近被請求資源的副本。它的作用故名思意,就是提供緩存機制的。若部署了Web緩存器,則可以配置瀏覽器,使得瀏覽器的HTTP請求首先發送至Web緩存器,下面我們通過一個例子來講解Web緩存器的機制。

  假設我現在要請求www.tewuyiang.cn這個服務器上的prop3.png這張圖片,結果將發生以下情況:

  1. HTTP客戶端創建一個到Web緩存器的TCP連接,並向Web緩存器發送一個請求報文;
  2. Web緩存器接收到請求報文,查看自己的本地是否包含被請求資源的副本,若包含,則由Web緩存器創建響應報文,並將此副本通過響應報文返回給HTTP客戶端;
  3. Web緩存器中不包含此資源的副本,則Web緩存器將向HTTP服務器(這里指的就是www.tewuyiang.cn)發起一個TCP連接,並向服務器請求客戶端需要的資源;
  4. 服務器創建響應報文,將請求的資源響應給緩存器,緩存器接收到響應報文,解析響應報文攜帶的資源,並復制一份副本存儲在本地,然后重新創建一份響應報文,並將副本封裝進其中,發送給最初請求資源的客戶端;

  通過上面的步驟我們可以看到,Web緩存器在這個過程中,既充當服務器的角色,又充當客戶端的角色。而部署了Web緩存器后,將大大減少服務器響應資源的時間。


 2.5 條件GET方法

  介紹完上面的Web緩存器后,很多人可能會有一個疑問:怎么能夠保證Web緩存器上的資源是最新的呢,若服務器上的資源被更新,而我們請求獲得的卻是緩存器上沒有被改變的舊資源怎么辦?HTTP自然是有辦法解決這個問題,這時候就要用到我們在講解響應報文時跳過的首部行Last-Modified了,而這種機制叫做條件GET

  Last-Modified首部行記錄的是當前被請求的資源,在服務器上最后被修改的時間。當我們請求一個Web緩存器上沒有的資源時,Web緩存器向HTTP服務器轉發該請求,而服務器響應緩存器,同時在響應報文中包含Last-Modified首部行。Web緩存器在存儲資源的副本時,同時也將Last-Modified的值存了下來。當下一次有客戶端請求此資源時,Web緩存器會發送一個條件GET請求到服務器,請求中包含這個時間值,且此時的命名為Last-Modified-Since。服務器接收到這個時間值后,將它與服務器本地記錄的這個資源的最后修改時間進行比較,若兩者相等,表示上次請求到這次請求之間,這個資源並未更新,服務器將告知Web緩存可以直接使用它存儲的副本;若兩者不相同,則服務器會將最新的資源,以及新的Last-Modified發送至Web緩存器,Web緩存器更新本地的副本,並響應給客戶端。


三、總結

  上面的內容對HTTP協議以及它的一些機制進行了一個大致的介紹,相信看完之后,能夠讓你對HTTP有一個大致的了解。當然HTTP的內容肯定不止這些,只是限於篇幅,以及我的知識儲備,這篇博客就先寫上這些吧。日后有時間,再寫一寫HTTP的其他部分,例如cookiesession


四、參考

《計算機網絡——自頂向下方法(原書第七版本)》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM