當面試時被問對http瞭解多少的時候(二)—— http 協議進階篇

前言

本篇文章爲 http 系列文章中的第二部分,更多文章參考 juejin.im/post/5e8c58…html

TCP/IP 網絡分層模型

TCP/IP 當初的設計者提出 「分層」 的概念,把複雜的網絡通訊劃分爲多個層次,再給每個層次分配不一樣的職責,層次內只須要專心作好本身的事情就好。用 「分而治之」 的思想把一個 「大麻煩」 拆分紅了數個 「小麻煩」,從而解決了網絡通訊的難題。web

下圖是 TCP/IP 協議棧的層次圖:瀏覽器

TCP/IP 協議棧總共有四層,就像搭積木同樣,每一層須要下層的支撐,同時又支撐着上層,任何一層被抽掉均可能致使整個協議棧的坍塌。它的層次是 「從下往上」 數的,因此第一層就是最下面的一層。緩存

1. 第一層:「連接層」(link layer)

這一層負責在以太網、WiFi 這樣的底層網絡上發送原始數據包,工做在網卡這個層次,使用 MAC 地址來標記網絡上的設備,因此有時候也叫MAC層。安全

2. 第二層:「網際層」或者「網絡互連層」(internet layer)

IP 協議就處在這一層。由於 IP 協議定義了 「IP地址」 的概念,因此就能夠在 「連接層」 的基礎上,使用 「IP 地址」 代替 「MAC地址」,把許許多多的局域網、廣域網鏈接成一個虛擬的巨大網絡,在這個網絡裏找設備時只要把 IP 地址再 「翻譯」 成 MAC 地址就能夠了。服務器

3. 第三層:「傳輸層」(transport layer)

這個層次協議的職責是保證數據在 IP 地址標記的兩點之間進行 「可靠」 地傳輸,是 TCP、UDP 協議工做的層次。網絡

TCP 與 UDP 的區別app

  1. 是否有狀態: TCP 是一個有狀態的協議,須要先與對象創建鏈接而後才能發送數據,並且保證數據不丟失不重複。而 UDP 則比較簡單,它無狀態,不用事先創建鏈接就能夠任意發送數據,但不保證數據會發到對方。
  2. 數據的形式: TCP 的數據是連續的 「字節流」,有前後順序。而 UDP 則是分散的小數據包,是順序發,亂序收。

4. 第四層:「應用層」(application layer)

因爲下面的三層把基礎打得很是好,因此在這一層就 「百花齊放」 了,有各類面向具體應用的協議。例如 SSH、HTTP、FTP 等。post

MAC 層的傳輸單位是幀(frame),IP 層的傳輸單位是包(package),TCP層的傳輸單位是段(segment),HTTP 的傳輸單位則是消息或報文(message)。但這些名詞並無什麼本質的區分,能夠通稱爲數據包。學習

OSI 網絡分層模型

OSI 的全稱是 「開放式系統互聯通訊參考模型」 (Open System Interconnection Reference Model)。

網絡模型不是一開始就有的,在網絡剛發展時,網絡協議是由各互聯網公司本身定義的,好比那時的巨頭網絡公司 IBM、微軟、蘋果、思科等等,他們每家公司都有本身的網絡協議,各家的協議也是不能互通的,那時候你們以爲這是能夠的,但對消費者來講這其實是技術壟斷,由於你買了蘋果的設備就不能用微軟的設備,由於他們的協議不是同樣的,沒有統一的標準來規範網絡協議,都是這些公司的私有協議。 這樣大大的阻礙了互聯網的發展,爲了解決這個問題,國際標準化組織 1984 提出的模型標準,簡稱 OSI(Open Systems Interconnection Model),這是一個標準,並不是實現。 TCP/IP 協議就是基於此模型設計。

OSI 模型分紅了七層,部分層次與 TCP/IP 很像,以下圖:

1. 物理層:網絡的物理形式,例如電纜、光纖、網卡、集線器等

2. 數據鏈路層,基本至關於 TCP/IP 的鏈路層

3. 網絡層:至關於 TCP/IP 裏的網際層

4. 傳輸層:至關於 TCP/IP 裏的傳輸層

5. 會話層:維護網絡中的鏈接狀態,即保持會話和同步

6. 表示層:把數據轉換爲合適、可理解的語法和語義

7. 應用層:面向具體的應用傳輸數據

不過國際標準組織內心也很清楚,TCP/IP 等協議已經在許多網絡上實際運行,再推翻重來是不可能的。因此,OSI 分層模型在發佈的時候就明確地代表是一個「參考」,不是強制標準。

但 OSI 模型也是有優勢的。對比一下就能夠看出,TCP/IP 是一個純軟件的棧,沒有網絡應有的最根基的電纜、網卡等物理設備的位置。而 OSI 則補足了這個缺失,在理論層面上描述網絡更加完整。

兩個分層模型的映射關係

如今咱們有了兩個網絡分層模型:TCP/IP 和 OSI,新的問題又出現了,一個是四層模型,一個是七層模型,這二者應該如何互相映射或者說互相解釋呢?

好在 OSI 在設計之初就參考了 TCP/IP 等多個協議,能夠比較容易但不是很精確地實現對應關係。

第一層:物理層,TCP/IP 裏無對應;

第二層:數據鏈路層,對應 TCP/IP的連接層;

第三層:網絡層,對應 TCP/IP 的網際層;

第四層:傳輸層,對應 TCP/IP 的傳輸層;

第5、6、七層:統一對應到 TCP/IP 的應用層。

TCP/IP 協議棧的工做方式

TCP/IP 協議棧是如何工做的呢?

http 協議的傳輸過程 經過協議棧逐層向下,依次通過應用層、傳輸層、網際層、鏈路層,每一層都添加本層的專有數據,層層打包,而後經過下層發送出去。

http 協議的接收數據過程 則是相反的操做,從下往上依次通過鏈路層、網際層、傳輸層、應用層,逐層拆包,每層去掉本層的專有頭部,上層就會拿到本身的數據。

下層的傳輸過程對於上層是徹底「透明」的,上層也不須要關心下層的具體實現細節,因此就 HTTP 層次來看,它無論下層是否是 TCP/IP 協議,看到的只是一個可靠的傳輸鏈路,只要把數據加上本身的頭,對方就能原樣收到。

你能夠把 http 利用 TCP/IP 協議棧傳輸數據想象成一個發快遞的過程。

假如你想把一件毛絨玩具送給朋友,這件玩具就至關於 http 協議裏要傳輸的內容,好比HTML。爲了保護玩具,你會給毛絨玩具套一個塑料袋,這個就至關於 http 協議加了一個 http 的協議頭。

你把玩具交給快遞小哥,爲了保護貨物,他加了層包裝貼了個標籤,至關於在 TCP 層給數據再次打包,加上了 TCP 的頭。

接着快遞小哥下樓,把包裹放進了三輪車裏,運到集散點,而後再裝進更大的卡車裏,至關於在 IP 層、MAC 層對 TCP 數據包加上了 IP頭、MAC 頭。

以後通過了漫長的運輸,包裹到達了目的地,要卸貨再放進另外一位快遞員的三輪車,就是在 IP 層、MAC 層傳輸後拆包。

快遞員到了你朋友的家門口,撕掉標籤,去除了 TCP 層的頭,你朋友再拆掉塑料包裝,也就是 http 頭,最後就拿到了毛絨玩具,也就是真正的 HTML 頁面。

HTTP協議的核心 —— HTTP報文

http 協議的核心部分是它傳輸的報文內容。

http 協議在規範文檔裏詳細定義了報文的格式,規定了組成部分、解析規則,還有處理策略等,因此能夠在 TCP/IP 層之上實現更靈活豐富的功能,例如鏈接控制、緩存管理、數據編碼、內容協商等。

TCP 報文結構

拿 TCP 報文舉例,它在實際要傳輸的數據以前附加了一個 20 字節的頭部數據,存儲 TCP 協議必須的額外信息,例如發送方的端口號、接收方的端口號包序號等。

有了這個附加的 TCP 頭,數據包纔可以正確的傳輸,到了目的地後把投不去掉,就能夠拿到真正的數據。

http 報文結構

http 協議與 TCP 協議相似,一樣也須要在實際傳輸的數據前附加一些頭數據,不過與 TCP 不一樣的是,它是一個 「純文本」 的協議,因此頭數據都是 ASCLL 碼的文本,能夠很容易的用肉眼閱讀,不用藉助程序也可以看懂。

http 協議的請求報文和響應報文的結構基本相同,由三大部分組成:

  1. 起始行:描述請求或相應的基本信息
  2. 頭部字段集合(header):使用 key - value 的形式更詳細的說明報文
  3. 消息正文:實際傳輸的數據,不必定是純文本,能夠是圖片、視頻等二進制數據

這其中前兩部分 起始行和頭部字段常常被合稱爲 「請求頭」「響應頭」「header」,消息正文又稱爲 「實體」「body」

http 協議規定報文必須有 header,但能夠沒有 body。就像你郵寄快遞的時候能夠郵寄空包裹同樣。可是規定 header 以後必需要有一個 「空行」,也就是 「CRLF」。雖然 http 協議對 header 的大小沒有作限制,可是各個 web 服務器都不容許過大的請求頭,由於頭部太大會佔用大量的服務器資源,影響運行效率。

一個完整的 http 報文就像是下圖的這個樣子,注意在 header 和 body 之間有一個 空行。

http 報文經常使用頭字段

類型區分

http 協議規定了很是多的頭部字段,實現各類各樣的功能,但基本上能夠分爲四大類:

  1. 通用字段:在請求頭和響應頭裏均可以出現
  2. 請求字段:僅能出如今請求頭裏,進一步說明請求信息或者額外的附加條件
  3. 響應字段:僅能出如今響應頭裏,補充說明響應報文的信息
  4. 實體字段:它實際上屬於通用字段,但專門描述 body 的額外信息

對 http 報文的解析和處理實際上主要就是對頭字段的處理,理解了頭字段也就理解了 http 報文。

經常使用的請求字段 Request Headers

  1. Accept:表示客戶端指望服務器返回的媒體格式(MIME),好比 text/html、mage/webp、 / 等,通配符*/* 表示任意類型的數據。

  2. Accept-encoding:向服務器申明客戶端(瀏覽器)接收的編碼方法,一般爲壓縮方法,好比 gzip 等。

  3. Accept-Language:向服務器申明客戶端接收的語言,好比 en-US、zh-CN 等。

  4. Cache-control:控制瀏覽器的緩存,好比 private、no-cache 等。

  5. Cookie:告訴服務器關於 Session 的信息,存儲讓服務器辨識用戶身份的信息等。

  6. Refer:是一個連接,告訴服務器該頁面是從哪一個頁面連接進來的。

  7. User-agent:向服務器發送瀏覽器的版本、系統、應用程序的信息。

  8. Connection:鏈接狀態,好比 keep-alive 指的是保持鏈接狀態,close 指關閉鏈接狀態。

經常使用的相應字段 Response Headers

  1. Content-length:是一個數字,表示 http 實體消息(body)的長度。
  2. Content-Type:表示服務器向客戶端發送的頭,表明內容的媒體類型和編碼格式的統一應答,好比 text/plain; charset=UTF-8。
  3. Content-Language:該字段是對 Accept-Language 的應答。服務器經過此字段告知客戶端返回的 Body 信息的語言是什麼。
  4. Date:若是服務器沒有緩存,那麼Date就是響應的即時生成時間。若是服務器設有緩存,那麼Date就是響應內容被緩存的時間。
  5. Expires:設置響應體的過時時間。若是在過時以前進行訪問,就會讀取緩存中的版本。
  6. Last-modified:設置該文件在服務器端中最後被修改的時間。

注:附一張常見媒體格式圖

http 的請求方法

請求方法是客戶端發出的、要求服務器執行的、對資源的一種操做;

請求方法的實際含義是客戶端對服務器端發出了一個 「動做指令」,要求服務端對 URI 定位的資源執行這個動做。目前 HTTP/1.1 規定了八種方法,單詞都必須是大寫的形式。

  1. GET:獲取資源,能夠理解爲讀取或者下載數據;
  2. HEAD:獲取資源的元信息;
  3. POST:向資源提交數據,至關於寫入或上傳數據;
  4. PUT:相似 POST;
  5. DELETE:刪除資源;
  6. CONNECT:創建特殊的鏈接隧道;
  7. OPTIONS:列出可對資源實行的方法;
  8. TRACE:追蹤請求 - 響應的傳輸路徑。

請求方法是對服務器的「指示」,真正應如何處理由服務器來決定;

既然請求方法是客戶端對服務器的一個 「指示」,那麼客戶端天然沒有決定權,服務端掌握着全部的資源,也就有絕對的決策權力。它收到 http 請求報文後,看到裏面的請求方法,能夠執行也能夠拒絕,會經過 http 狀態相應碼告訴客戶端,好比:

  1. 假如你訪問的這個文件不存在,那麼會返回給你一個 404
  2. 假如你訪問的這個文件存在,可是不容許訪問,那麼可能會給你返回一個 403 forbidden 等

四種經常使用的請求方法

最經常使用的請求方法是 GET 和 POST,分別是獲取數據和發送數據;

GET/HEAD

  1. GET 方法應該是 http 協議裏最知名也是用的最多的請求方法了。它的含義是請求 從服務端獲取資源,這個資源能夠是文本、頁面、圖片、視頻、HTML頁面等
  2. HEAD 方法與 GET 方法相似,也是請求從服務器獲取資源,但服務器不會返回請求的實體數據,只會傳回響應頭。HEAD 方法能夠看做是 GET 方法的 「簡化版」,由於它的響應頭與 GET 徹底相同,因此能夠用在不少不須要 body 的場景,避免傳輸 body 數據的浪費。好比想要檢查一個文件是否存在,只要發個 head 請求就能夠了,沒有必要用 GET 把整個文件都取下來。

POST/PUT

GET 和 HEAD 方法是從服務器獲取數據,而 POST 和 PUT 方法則是相反操做,向 URI 指定的資源提交數據,數據就放在報文的 body 裏。

  1. POST 也是一個常常用到的請求方法,使用頻率應該是僅次於 GET,應用的場景也很是多,只要向服務器發送數據,用到的大多數都是 POST。

好比,你在掘金上寫了一篇文章,此時點擊發布的時候要上傳你的文章到掘金的服務器,此時執行的就是一次 POST 請求。

  1. PUT 的做用與 POST 相似,也能夠向服務器提交數據,但與 POST 存在微妙的不一樣,一般 POST 表示的是 「新建」「create」 的含義,而 PUT 則是 「修改」「update」 的含義。能夠對比一下 SQL 來加深理解:把 POST 理解成 INSERT,把 PUT 理解成 UPDATE,屢次 INSERT 會添加多條記錄,而屢次 UPDATE 只操做一條記錄,並且效果相同。在實際應用中,PUT 用到的比較少,由於它與 POST 的語義、功能太過近似。

請求方法的兩個重要概念:安全 和 冪等

  • 安全

    在 http 協議裏,所謂的 「安全」 是指請求方法不會 「破壞」 服務器上的資源,即不會對服務器上的資源形成實質的修改。

    按照這個定義,只有 GET 和 HEAD 方法是 「安全」 的,由於它們是 「只讀」 操做,不管被訪問多少次,服務器上的數據都是 「安全」的。而 POST、PUT、DELETE 等操做會修改服務器上的資源,增長或刪除數據,因此是 「不安全」 的。

  • 冪等

    所謂 「冪等」 其實是一個數學用語,被借用到了 http 協議裏,意思是屢次執行相同的操做,結果也都是相同的,即屢次 「冪」 後結果 「相等」。

    好比 POST 方法屢次操做,每次獲得的結果不同,因此不是 「冪等」 的。

http 的響應狀態碼

在以前的學習中咱們提到了客戶端向服務端發起請求,服務端會返回狀態碼告訴客戶端,表示了服務器對請求的處理結果。目前 RFC 標準裏規定的狀態碼是三位數, RFC 標準把狀態碼分紅了五類,用數字的第一位表示分類。這五類的具體含義是:

  1. 1xx:提示信息,表示目前是協議處理的中間狀態,還須要後續的操做
  2. 2××:成功,報文已經收到並被正確處理
  3. 3××:重定向,資源位置發生變更,須要客戶端從新發送請求
  4. 4××:客戶端錯誤,請求報文有誤,服務器沒法處理
  5. 5××:服務器錯誤,服務器在處理請求時內部發生了錯誤。
相關文章
相關標籤/搜索