面試官常問的HTTP知識點

語言: CN / TW / HK

網際網路中的資料是通過資料包來傳輸的,IP通過DNS查詢IP地址進而把資料包送達目的主機,UDP接過資料包,通過埠號把資料包送往具體的應用,而使用TCP可保證資料的完整性

當傳輸層TCP/IP協議將資料傳輸到網路上時,瀏覽器可通過HTTP協議進行文字傳輸,物聯網可通過MQTT協議進行互動

一、UDP

UDP傳輸非常快,適合線上影片、互動遊戲這類強互動的場景

對於資料可靠性有要求的場景則不太適合,它有個大缺點:不能保證資料可靠性

  • 不提供重發機制,直接丟棄當前的包
  • 傳送之後不售後,無法確認是否到達目的地
  • 無法還原資料包成完整的檔案

但它的兄弟TCP可以代勞

二、TCP

TCP是一種面向連線的、可靠的、基於位元組流的傳輸層通訊協議。解決了丟失資料包的問題,並且提供了組裝資料包的能力。這不得不感謝傳送端不僅給它提供了源埠號和目標埠號,還提供了序列號,引入了資料包排列機制

1、連線過程

1.1、建立連線

TCP是面向連線的,在資料通訊之前就做好兩端的準備工作,在客戶端和服務端通過三個資料包來確認連線的建立

  • 一開始,客戶端和服務端都處於 close狀態,接著服務端主動監聽某個埠,處於listen狀態
  • 客戶端生成初始序列號client_isn置於TCP首部的序列號中,同時更改SYN標誌為1向伺服器發起連線,之後處於SYN-SENT狀態
  • 服務端收到SYN報文同樣生成初始序列號server_isn置於TCP首部的序列號中,並將客戶端序列號+1置於TCP首部的確認應答號中,同時更改SYNACK標誌為1,傳送SYN + ACK報文並更改狀態為SYN_RCVD
  • 客戶端收到SYN + ACK報文,將服務端序列號+1填入確認應答號並回復ACK應答報文變更狀態為established
  • 伺服器收到應答後也進入established狀態

只有第三次握手可以攜帶資料,前面兩次是不可攜帶資料的

1.2、為什麼三次握手?

  • 通過三次握手能防止歷史連線的建立,能減少雙方不必要的資源開銷,能幫助雙方同步初始化序列號
  • 兩次握手無法仿製歷史連線的建立,會造成雙方資源的浪費,也無法可靠的同步雙方序列號
  • 四次握手:三次握手就已經理論上最少可靠連線建立,因此不需要使用更多的通訊次數

2、傳輸資料

  • TCP是可靠的,接收端必須對每個資料包進行確認操作,即重發機制

當傳送端傳送了一個數據包之後,在規定時間內沒有接收到反饋的確認資訊,則判斷資料包丟失,觸發重發機制

  • TCP是基於位元組流的,接收端可通過TCP提供的序號進行排序,進而保證資料的完整性,即排列機制

3、斷開過程

3.1、斷開連線

  • 客戶端主動關閉連線,傳送FIN報文,即更改FIN標誌為1同時進入FIN_WAIT_1狀態
  • 服務端收到報文後發出ACK應答報文,接著進入CLOSED_WAIT狀態
  • 客戶端收到報文後,進入FIN_WAIT_2狀態
  • 伺服器處理完成後發出FIN報文,並進入LAST_ACK狀態
  • 客戶端收到報文後發出ACK應答報文,接著進入TIME_WAIT狀態
  • 伺服器收到ACK應答報文後完成連線關閉
  • 客戶端 等待兩倍報文最大生存時間(MSL)後 自動進入close狀態,完成連線關閉

主動關閉連線的,才有TIME_WAIT狀態

3.2、為什麼四次揮手?

  • 關閉連線時,客戶端向服務端傳送FIN時,僅代表客戶端不再發送資料但能接收資料
  • 服務端接收到FIN時,回覆一個ACK,僅代表收到報文,但伺服器可能還有資料需要處理和傳送,確保不再發送資料時才傳送FIN給到客戶端表示同意現在關閉連線

三、HTTP

HTTP 協議以 ASCII 碼傳輸,構建於 TCP/IP 協議之上的應用層協議,預設埠號是 80,它是無連線無狀態的超文字傳輸協議

1、HTTP 報文

1.1、請求報文

規範把 HTTP 請求分為三個部分:請求行、請求頭 和 訊息主體

[method] [url] [version]
[headers]

[body] 

HTTP 中的GETPOSTPUTDELETE對應著資源的查、增、改、刪4個操作

1.1.1、GET

只讀操作,是安全且冪等的

  • 安全:請求方法不會破壞伺服器上的資源
  • 冪等:多次執行相同的操作,結果都是相同的
1.1.2、POST

讀寫操作,是不安全且不冪等的

1.1.3、PUT

不同於POSTPUT是冪等的

1.1.4、OPTIONS

用以從伺服器獲取更多資訊

1.2、響應報文

同樣HTTP響應分為三個部分:狀態行、響應頭 和 響應正文

[version] [status code] [status msg]
[headers]

[body]
  • 常見的狀態碼有
狀態碼 狀態描述 備註
206 Partial Content 範圍響應,主體包含所請求的資料區間<br/>斷點續傳時通過 Range 指定區間
301 Moved Permanently 請求永久重定向
302 Moved Temporarily 請求臨時重定向
304 Not Modified 未修改,使用快取檔案(協商快取)
400 Bad Request 客戶端請求有語法錯誤
401 Unauthorized 請求未經授權(同WWW-Authenticate一起使用)<br/>在後續請求中攜帶 Authorization用於驗證使用者代理身份的憑證
403 Forbidden 伺服器拒絕提供服務,通常在響應正文給出原因
404 Not Found 請求資源不存在
500 Internal Server Error 伺服器發生不可預期的錯誤
503 Service Unavailable 伺服器當前無法處理請求,需等待伺服器恢復正常

2、HTTP 演變

版本 核心訴求 新增特性
HTTP/1.0 支援多種型別的檔案下載 引入請求頭、響應頭、狀態碼
HTTP/1.1 提高對頻寬的利用率 1、持久連線(每個域名最多同時維護 6 個 TCP 持久連線) 2、使用 CDN 實現域名分片機制 3、提供虛擬主機的支援(Host 欄位) 4、增加快取策略 5、安全機制(CORS)
HTTP/2.0 提升網路速度 1、多路複用 2、設定請求的優先順序 3、伺服器推送 4、頭部壓縮 5、二進位制格式
HTTP/3.0 構建高效網路 1、甩掉TCP、TLS 的包袱,使用UDP協議 2、QUIC協議
HTTPS 構建安全HTTP 引入SSL 、混合加密、摘要演算法 、數字證書

2.1、持久連線

HTTP/1.1 中增加了持久連線的方法,即在一個 TCP 連線上可以傳輸多個 HTTP 請求,只要瀏覽器或者伺服器沒有明確斷開連線,那麼該 TCP 連線會一直保持,提升了整體 HTTP 的請求時長。目前瀏覽器中對於同一個域名,預設允許同時建立 6 個 TCP 持久連線

Connection: Keep-Alive;  // HTTP/1.1預設使用持久連線,如需關閉,請求頭Connection設定為close
Keep-Alive: timeout=5, max=100; // HTTP 長連線不可能一直保持,timeout=5 表示這個TCP通道可以保持5秒,max=100,表示這個長連線最多接收100次請求就斷開

2.2、使用 CDN 實現域名分片機制

2.3、提供虛擬主機的支援

Host表示當前的域名地址,伺服器可以根據不同的 Host 值做不同的處理

Host: <host>:<port>; // host: 伺服器的域名(用於虛擬主機) port: 伺服器監聽的 TCP 埠號

2.4、快取策略

快取策略

2.5、安全機制

2.5.1、會話跟蹤

HTTP是無狀態協議,即瀏覽器對於事務的處理沒有記憶能力,可通過CookieJWT機制來進行會話跟蹤

  • Cookie機制

服務端第一次收到請求時建立session物件生成對應的sessionID,將其放進Set-Cookie傳送給客戶端,下一次訪問時,客戶端攜帶sessionID請求服務端,服務端可通過sessionID識別使用者資訊

Cookie 的過期時間、域、路徑、有效期、適用站點都可以根據需要來指定

功能 屬性 例子 補充說明
定義 Cookie 的生命週期 Expires <br/> Max-Age Set-Cookie: key=value; Expires=Wed, 21 Oct 2022 07:28:00 GMT 設定的日期和時間只與客戶端相關,會話期 Cookie 僅在會話期內有效
限制訪問 Cookie HttpOnly<br/>Secure Set-Cookie: key=value; Secure; HttpOnly HttpOnly:僅作用於伺服器<br/>Secure僅適用於 HTTPS 協議加密過的請求
Cookie 的作用域 Domain<br/>Path Set-Cookie:Domain=mozilla.org;Path=/docs Domain 指定了哪些主機可以接受 Cookie<br/>Path 指定了主機下的哪些路徑可以接受 Cookie
SameSite None<br/>Strict<br/>Lax Set-Cookie: key=value; SameSite=Strict None:瀏覽器會在同站請求、跨站請求下繼續傳送 cookies(舊版本瀏覽器預設選項)<br/>Strict:瀏覽器將只在訪問相同站點時傳送 cookie<br/>Lax:與 Strict 類似,但使用者從外部站點導航至URL時除外(新版本瀏覽器預設選項)
  • JWT機制 (JSON Web Token)

Cookies 只適用於單節點的域 或 節點的子域,若通過第三個節點訪問會被禁止。而JWT機制則支援跨域認證,可通過多個節點進行使用者認證

服務端第一次收到請求時,進行認證後生成一個 Token(簽名後的JSON 物件)傳送給客戶端。客戶端可將收到的jwt儲存在CookielocalStorage上,之後每次與服務端通訊都攜帶上,可通過Cookie自動傳送,但這種方式不能跨域,比較推薦通過 POST 請求的資料體 或 Authorization進行傳遞

注意喔,JWT 的 Cookie 資訊儲存在客戶端,即服務端是無狀態的

2.5.2、跨源資源共享(CORS)

CORS

規範要求那些可能產生副作用的請求,瀏覽器必須首先使用OPTIONS方法發起一個預檢請求,從而獲知服務端是否允許跨域請求。伺服器確認允許後才發起實際的HTTP請求。在預檢請求的返回中,服務端可通知客戶端是否需要攜帶身份憑證

  • 簡單請求

若請求滿足下述所有條件,則稱之為簡單請求,它不會觸發預檢請求

1、使用GETHEADPOST請求方法 2、Content-Type的值僅限於text/plainmultipart/form-dataapplication/x-www-form-urlencoded 3、請求中沒有註冊任何事件監聽器,沒有使用 ReadableStream 物件

// 附帶身份憑證的簡單請求
withCredentials:true; // 向伺服器傳送 Cookies
Access-Control-Allow-Credentials: true; // 服務端允許附帶身份憑證
  • 複雜請求
響應頭 例子 說明
Access-Control-Allow-Origin Access-Control-Allow-Origin: <origin>/* Vary: Origin origin:指定允許訪問該資源的URI<br/>若指定了具體的域名,則Vary的值必須包含Origin,表明服務端按URI返回對應內容
Access-Control-Expose-Headers Access-Control-Expose-Headers: X-My-Custom-Header 伺服器把允許瀏覽器訪問的頭放入白名單
Access-Control-Allow-Credentials Access-Control-Allow-Credentials: true 指定了credentials:true時是否允許瀏覽器讀取 response 的內容<br/>在預檢請求的響應時,指定實際的請求是否可以使用 credentials
Access-Control-Max-Age Access-Control-Max-Age: 86400 預檢請求的結果在多少秒內有效
Access-Control-Allow-Methods Access-Control-Allow-Methods: <method>[, <method>]* 預檢請求的響應,指明瞭實際請求所允許使用的 HTTP 方法
Access-Control-Allow-Headers Access-Control-Allow-Headers: <field-name>[, <field-name>]* 預檢請求的響應,指明瞭實際請求中允許攜帶的首部欄位

2.6、支援動態生成內容

伺服器會將資料分割成若干個任意大小的資料塊,每個資料塊傳送時會附上上個數據塊的長度,最後使用一個零長度的塊作為傳送資料完成的標誌,因此對於下載請求來說,是沒有辦法實現進度的

Transfer-Encoding: gzip, chunked;  // 分塊:chunked 壓縮演算法:compress、deflate、gzip

2.7、多路複用

一個域名只使用一個TCP長連線來傳輸資料,這樣整個頁面資源的下載過程只需要一次慢啟動,避免了多個 TCP 連線競爭頻寬的問題。移除了序列請求,順應的解決了隊頭阻塞問題

2.8、設定請求的優先順序

每個資料流都標記著獨一無二的編號,客戶端可以指定資料流的優先順序

2.9、伺服器推送

服務端主動向客戶端傳送訊息,即:當用戶請求一個 HTML 頁面之後,伺服器知道該 HTML 頁面會引用幾個重要的 JavaScript 檔案和 CSS 檔案,那麼在接收到 HTML 請求之後,附帶將要使用的 CSS 檔案和 JavaScript 檔案一併傳送給瀏覽器,這樣當瀏覽器解析完 HTML 檔案之後,就能直接拿到需要的 CSS 檔案和 JavaScript 檔案,大大提升了頁面首次渲染速度

2.10、頭部壓縮

HTTP/2.0引入HPACK演算法:在客戶端和伺服器同時維護一張頭資訊表,所有欄位都會存入這個表生成一個索引號,相同欄位只發送對應的索引號,即:同時發出多個請求,請求頭一樣或相似,則協議會將重複部分消除

2.11、二進位制格式

HTTP/2.0 全面採用二進位制格式,頭資訊和資料體都是二進位制,統稱為「幀」提高了資料傳輸的效率

2.12、QUIC協議

  • 實現了類似 TCP 的流量控制、傳輸可靠性的功能
  • 集成了 TLS 加密功能,減少了握手所花費的 RTT 個數
  • 實現了 HTTP/2 中的多路複用功能

不同於 TCP,QUIC 實現了在同一物理連線上可以有多個獨立的邏輯資料流,實現了資料流的單獨傳輸,避免了 TCP 中隊頭阻塞的問題

  • 實現了快速握手功能,基於 UDPQUIC 可使用 0-RTT|1-RTT 來建立連線

3、HTTPS

HTTPSHTTPTCP之間加了一層用於加解密的SSL/TLS協議,通過資訊加密、校驗機制 和 身份證書 保證通訊的安全性

  • 客戶端 傳送 對稱加密套件列表、非對稱加密套件列表 和 客戶端隨機數 給到服務端
  • 服務端 儲存 客戶端隨機數 和 私鑰,回覆 選中的對稱加密套件、非對稱加密套件 和 服務端隨機數 以及 數字證書
  • 客戶端向 CA機構驗證數字證書,證實服務端身份並獲取公鑰
  • 客戶端利用兩端的隨機數計算出pre-master,並用獲取到的公鑰進行加密,傳送加密後的pre-master
  • 服務端拿出私鑰進行解密,得到pre-master
  • 服務端和客戶端使用這三組隨機數生成會話金鑰,並返回確認訊息
  • 之後使用對稱加密進行通訊

3.1、混合加密

HTTPS通過非對稱加密交換「會話金鑰」後續通訊使用對稱加密,這是由於

  • 非對稱加密使用兩個金鑰:公鑰和私鑰,公鑰可儲存在CA機構同時儲存私鑰。可以安全的進行金鑰交換,但速度慢
  • 對稱加密只使用一個金鑰,無法做到安全的金鑰交換,但速度快

3.2、摘要演算法

摘要演算法通過生成唯一的指紋,用於校驗資料的完整性。客戶端在進行通訊前會通過摘要演算法得出明文的指紋,請求時將指紋和明文一併加密,服務端收到密文後進行解密,比對攜帶的指紋和當前計算的指紋是否一致,一致則說明資料完整

3.3、數字證書

權威機構CA簽發認證的數字證書【包含了公鑰、組織資訊、CA資訊、有效時間、證書序列號、CA生成的數字簽名等】這些資訊是明文的,同時可向瀏覽器證明伺服器的身份

四、MQTT

MQTT是基於二進位制訊息的釋出/訂閱程式設計模式的訊息協議,非常適合需要低功耗和網路頻寬有限的IoT場景

  • 裝置連線

裝置通過MQTT協議連線到物聯網雲服務,進而可以進行裝置管理及資料管理

  • 訊息型別

MQTT擁有14種不同的訊息型別,比如CONNECT表示客戶端連線到MQTT代理,CONNACK表示連線確認

  • 主題

MQTT提供了主題對訊息進行分類,訊息是一個UTF-8的字串,通過類似正則的規則進行匹配分類,比如:+可以過濾一個層級,*可以過濾任意級別的層級(必須在主題最後)

  • 服務質量

MQTT提供級別0級別1級別2三種服務質量

服務質量 訊息可靠性 解釋
級別0 盡力而為 不提供重發
級別1 至少一次 提供重發,併發可能造成重複訊息
級別2 恰好一次 不丟失不重複,但增加延時減少併發