本篇文章爲 http 系列文章中的第二部分,更多文章參考 juejin.im/post/5e8c58…html
TCP/IP 當初的設計者提出 「分層」 的概念,把複雜的網絡通訊劃分爲多個層次,再給每個層次分配不一樣的職責,層次內只須要專心作好本身的事情就好。用 「分而治之」 的思想把一個 「大麻煩」 拆分紅了數個 「小麻煩」,從而解決了網絡通訊的難題。web
下圖是 TCP/IP 協議棧的層次圖:瀏覽器
TCP/IP 協議棧總共有四層,就像搭積木同樣,每一層須要下層的支撐,同時又支撐着上層,任何一層被抽掉均可能致使整個協議棧的坍塌。它的層次是 「從下往上」 數的,因此第一層就是最下面的一層。緩存
這一層負責在以太網、WiFi 這樣的底層網絡上發送原始數據包,工做在網卡這個層次,使用 MAC 地址來標記網絡上的設備,因此有時候也叫MAC層。安全
IP 協議就處在這一層。由於 IP 協議定義了 「IP地址」 的概念,因此就能夠在 「連接層」 的基礎上,使用 「IP 地址」 代替 「MAC地址」,把許許多多的局域網、廣域網鏈接成一個虛擬的巨大網絡,在這個網絡裏找設備時只要把 IP 地址再 「翻譯」 成 MAC 地址就能夠了。服務器
這個層次協議的職責是保證數據在 IP 地址標記的兩點之間進行 「可靠」 地傳輸,是 TCP、UDP 協議工做的層次。網絡
TCP 與 UDP 的區別app
因爲下面的三層把基礎打得很是好,因此在這一層就 「百花齊放」 了,有各類面向具體應用的協議。例如 SSH、HTTP、FTP 等。post
MAC 層的傳輸單位是幀(frame),IP 層的傳輸單位是包(package),TCP層的傳輸單位是段(segment),HTTP 的傳輸單位則是消息或報文(message)。但這些名詞並無什麼本質的區分,能夠通稱爲數據包。學習
OSI 的全稱是 「開放式系統互聯通訊參考模型」 (Open System Interconnection Reference Model)。
網絡模型不是一開始就有的,在網絡剛發展時,網絡協議是由各互聯網公司本身定義的,好比那時的巨頭網絡公司 IBM、微軟、蘋果、思科等等,他們每家公司都有本身的網絡協議,各家的協議也是不能互通的,那時候你們以爲這是能夠的,但對消費者來講這其實是技術壟斷,由於你買了蘋果的設備就不能用微軟的設備,由於他們的協議不是同樣的,沒有統一的標準來規範網絡協議,都是這些公司的私有協議。 這樣大大的阻礙了互聯網的發展,爲了解決這個問題,國際標準化組織 1984 提出的模型標準,簡稱 OSI(Open Systems Interconnection Model),這是一個標準,並不是實現。 TCP/IP 協議就是基於此模型設計。
OSI 模型分紅了七層,部分層次與 TCP/IP 很像,以下圖:
不過國際標準組織內心也很清楚,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 協議棧是如何工做的呢?
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 協議在規範文檔裏詳細定義了報文的格式,規定了組成部分、解析規則,還有處理策略等,因此能夠在 TCP/IP 層之上實現更靈活豐富的功能,例如鏈接控制、緩存管理、數據編碼、內容協商等。
拿 TCP 報文舉例,它在實際要傳輸的數據以前附加了一個 20 字節的頭部數據,存儲 TCP 協議必須的額外信息,例如發送方的端口號、接收方的端口號包序號等。
有了這個附加的 TCP 頭,數據包纔可以正確的傳輸,到了目的地後把投不去掉,就能夠拿到真正的數據。
http 協議與 TCP 協議相似,一樣也須要在實際傳輸的數據前附加一些頭數據,不過與 TCP 不一樣的是,它是一個 「純文本」 的協議,因此頭數據都是 ASCLL 碼的文本,能夠很容易的用肉眼閱讀,不用藉助程序也可以看懂。
http 協議的請求報文和響應報文的結構基本相同,由三大部分組成:
這其中前兩部分 起始行和頭部字段常常被合稱爲 「請求頭」 或 「響應頭」 或 「header」,消息正文又稱爲 「實體」 或 「body」。
http 協議規定報文必須有 header,但能夠沒有 body。就像你郵寄快遞的時候能夠郵寄空包裹同樣。可是規定 header 以後必需要有一個 「空行」,也就是 「CRLF」。雖然 http 協議對 header 的大小沒有作限制,可是各個 web 服務器都不容許過大的請求頭,由於頭部太大會佔用大量的服務器資源,影響運行效率。
一個完整的 http 報文就像是下圖的這個樣子,注意在 header 和 body 之間有一個 空行。
http 協議規定了很是多的頭部字段,實現各類各樣的功能,但基本上能夠分爲四大類:
對 http 報文的解析和處理實際上主要就是對頭字段的處理,理解了頭字段也就理解了 http 報文。
Accept:表示客戶端指望服務器返回的媒體格式(MIME),好比 text/html、mage/webp、 / 等,通配符*/* 表示任意類型的數據。
Accept-encoding:向服務器申明客戶端(瀏覽器)接收的編碼方法,一般爲壓縮方法,好比 gzip 等。
Accept-Language:向服務器申明客戶端接收的語言,好比 en-US、zh-CN 等。
Cache-control:控制瀏覽器的緩存,好比 private、no-cache 等。
Cookie:告訴服務器關於 Session 的信息,存儲讓服務器辨識用戶身份的信息等。
Refer:是一個連接,告訴服務器該頁面是從哪一個頁面連接進來的。
User-agent:向服務器發送瀏覽器的版本、系統、應用程序的信息。
Connection:鏈接狀態,好比 keep-alive 指的是保持鏈接狀態,close 指關閉鏈接狀態。
注:附一張常見媒體格式圖
請求方法是客戶端發出的、要求服務器執行的、對資源的一種操做;
請求方法的實際含義是客戶端對服務器端發出了一個 「動做指令」,要求服務端對 URI 定位的資源執行這個動做。目前 HTTP/1.1 規定了八種方法,單詞都必須是大寫的形式。
請求方法是對服務器的「指示」,真正應如何處理由服務器來決定;
既然請求方法是客戶端對服務器的一個 「指示」,那麼客戶端天然沒有決定權,服務端掌握着全部的資源,也就有絕對的決策權力。它收到 http 請求報文後,看到裏面的請求方法,能夠執行也能夠拒絕,會經過 http 狀態相應碼告訴客戶端,好比:
最經常使用的請求方法是 GET 和 POST,分別是獲取數據和發送數據;
GET/HEAD
POST/PUT
GET 和 HEAD 方法是從服務器獲取數據,而 POST 和 PUT 方法則是相反操做,向 URI 指定的資源提交數據,數據就放在報文的 body 裏。
好比,你在掘金上寫了一篇文章,此時點擊發布的時候要上傳你的文章到掘金的服務器,此時執行的就是一次 POST 請求。
安全
在 http 協議裏,所謂的 「安全」 是指請求方法不會 「破壞」 服務器上的資源,即不會對服務器上的資源形成實質的修改。
按照這個定義,只有 GET 和 HEAD 方法是 「安全」 的,由於它們是 「只讀」 操做,不管被訪問多少次,服務器上的數據都是 「安全」的。而 POST、PUT、DELETE 等操做會修改服務器上的資源,增長或刪除數據,因此是 「不安全」 的。
冪等
所謂 「冪等」 其實是一個數學用語,被借用到了 http 協議裏,意思是屢次執行相同的操做,結果也都是相同的,即屢次 「冪」 後結果 「相等」。
好比 POST 方法屢次操做,每次獲得的結果不同,因此不是 「冪等」 的。
在以前的學習中咱們提到了客戶端向服務端發起請求,服務端會返回狀態碼告訴客戶端,表示了服務器對請求的處理結果。目前 RFC 標準裏規定的狀態碼是三位數, RFC 標準把狀態碼分紅了五類,用數字的第一位表示分類。這五類的具體含義是: