淺顯易懂的前端知識點(二)——HTTP協議基礎

kurryluo發表於2019-06-04

HTTP 協議的初印象:

是基於 TCP/IP 協議的應用層協議,不涉及資料包的傳輸,主要規定了客戶端和伺服器之間的通訊格式,預設使用 80 埠。

1 HTTP 協議 0.9 版(1991 年)

是個弱智協議,客戶端發起請求以後,伺服器只能返回 HTML 格式的字串,不能迴應別的格式。

只有一個 GET 命令:

GET /index.html

上面命令表示,TCP 連線(connection)建立後,客戶端向伺服器請求(request)網頁 index.html。

伺服器傳送完畢,就關閉 TCP 連線。

2 HTTP 協議 1.0 版(1996 年)

與 0.9 版本相比,有以下幾點變化:

  • 這個版本允許傳送的內容變多了,不僅可以傳輸文字,還能傳輸影象、視訊、二進位制檔案。
  • 除了 GET,POST、HEAD 這兩個命令都可以用,瀏覽器和伺服器的互動手段增加了。
  • HTTP 請求和迴應的格式也變了。每次通訊都必須包括頭資訊,用來描述一些後設資料。

新增的功能還有:

  • 狀態碼
  • 多字符集支援
  • 多部分傳送
  • 許可權
  • 快取
  • 內容編碼
2.1 請求形式:
<!-- 請求命令, 必須在尾部新增協議版本(HTTP/1.0)-->
GET /HTTP/1.0
<!-- 多行頭資訊,描述了客戶端的情況 -->
User-Agent: Mozilla/5.0(Macintosh: Intel Mac PS X 10_10_5)
<!-- 客戶端表示自己可以接受任何格式的資料 -->
Accept:*/*
2.2 迴應格式
<!-- 頭資訊 -->
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires:Thu, 05 Dec 1997 16:00:00 GMT
Server: Apache 0.84

<!-- 資料 -->
<html>
  <body>Hello World</body>
</html>

其中,頭資訊的第一行是 “協議的版本 + 狀態碼(status code) + 狀態描述”

2.3 Content-Type 欄位

Content-Type 欄位的作用是告訴客戶端從服務端返回的資料是什麼格式。

常見的 ContentType:

  • text/plain
  • text/html
  • text/css
  • image/jpeg
  • image/png
  • image/svg+xml
  • audio/mp4
  • video/mp4
  • application/javascript
  • application/pdf
  • application/zip
  • application/atom+xml

資料型別的構成包括一級型別和二級型別,中間用斜槓隔開。這些型別都被稱為 MIME type。

MIME type 不僅用於 HTTP 請求,也可以用於別的地方,比如 HTML 網頁。

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- 等同於 -->
<meta charset="utf-8" /> 
2.4 資料壓縮

客戶端在請求的時候,用 Accept - Encoding 欄位說明自己可以接受哪些壓縮方法。

Accept-Encoding: gzip, deflate

而伺服器使用 Content-Encoding 欄位說明資料的壓縮方法。

Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate
2.5 HTTP/1.0 協議的缺點

每個 TCP 連線只能傳送一個請求,資料傳送完畢連線就關閉了,如果要請求別的資源,必須再新建一個連線。

但是 TCP 連線的成本很高,因為客戶端和伺服器的三次握手,並且啟動傳送的速率較慢。

有一些瀏覽器為了解決 TCP 會關閉的問題,採用了非標準的 Connection 欄位。

瀏覽器請求和伺服器迴應都帶有這個欄位:

Connection: keep-alive

這樣的話,一個可以複用的連線建立了,直到客戶端或者伺服器主動關閉連線。但是不同的瀏覽器實現不同,這不是一個好的解決辦法。

3 HTTP 協議 1.1 版(1997 年)

3.1 持久連線

相比 1.0 版,1.1 版最大的變化是保持連線,即預設 TCP 連線不關閉,可以被多個請求複用,不用再宣告 Connection: keep-alive。

那怎麼關閉呢?如果客戶端或者伺服器發現對方一段時間內沒有活動,就可以主動關閉連線。不過最好還是客戶端在傳送最後一個請求的時候,傳送一個 Connection:close,明確要求伺服器關閉 TCP 連線。

另外,對於同一個域名,大多數瀏覽器允許同時建立 6 個持久連線。

3.2 管道機制

管道機制: 在同一個 TCP 連線裡,客戶端可以同時傳送多個請求。

以前的做法是客戶端先傳送 A 請求,然後再傳送 B 請求。管道機制是允許瀏覽器同時傳送 A 請求和 B 請求,但是伺服器還是按照順序進行的,先回應 A 請求再回應 B 請求。

3.3 區分資料包

一個 TCP 連線現在可以傳送多個迴應,勢必就要有一種機制,區分資料包是屬於哪一個迴應的。

Content-length 欄位的作用,宣告本次迴應的資料長度。

Content-Length: 3495

上面的欄位告訴客戶端,本次迴應的長度是 3495 個位元組,後面的位元組就屬於下一個迴應了。

所以,使用 Content-Length 欄位的前提條件是,伺服器傳送迴應之前,必須知道迴應的資料長度。

而在 1.0 版本中,這個欄位可以存在,也可以不存在,因為服務端關閉了 TCP 連線說明資料包已經全了。

3.4 其他功能

1.1 版新增了很多動詞方法:PUT、PATCH、HEAD、OPTIONS、DELETE。

客戶端的請求頭資訊增加了 Host 欄位,用來指定伺服器的域名。

這個欄位可以將請求發往同一臺伺服器的不同網站。

如:

Host: www.example.com
3.5 缺點

"隊頭堵塞": 在 1.1 版協議中,雖然可以在一個 TCP 中傳送多個請求,伺服器只有處理完一個迴應,才會進行下一個迴應。要是前面的迴應特別慢,後面就會有許多請求排隊等著。

為了避免這個問題,只有兩種方法:一是減少請求數,二是同時多開持久連線。

所以產生了很多網頁優化技巧,比如合併指令碼和樣式表,將圖片嵌入 CSS 程式碼,域名分片等,但是 HTTP 協議設計得更好的話,這些工作完全沒有必要做的。

4 SPDY 協議 (2009 年)

2009 年,谷歌公開了自己搞的 SPDY 協議,主要為了解決 HTTP/1.1 效率不高的問題。

這個協議最終被當作了 HTTP/2 的基礎。

5 HTTP 協議 2 版

HTTP/2 協議不叫 HTTP/2.0,這是因為標準委員會不在打算髮布子版本,下一個新的版本將會是 HTTP/3。

5.1 二進位制協議

HTTP 協議的頭肯定是文字(ASCII 碼),資料體可以是文字,也可以是二進位制。

但 HTTP/2 協議頭和資料體都是二進位制,是一個徹徹底底的二進位制協議。

這裡的頭和資料體都換了一個身份叫做 “幀”:頭資訊幀和資料幀。

二進位制協議的好處就是可以定義額外的幀,HTTP/2 有近十種幀,為將來的高階應用打好了基礎,因為二進位制解析比文字解析更方便。

5.2 多工

HTTP/2 協議複用 TCP 連線,也就是說客戶端和服務端可以同時傳送或者回應多個請求。

比如說,在一個 TCP 裡,客戶端給服務端傳送了 A 和 B 兩個請求,按道理說應該先處理 A 請求,但是服務端發現 A 請求有點費勁兒,就先把 A 請求中處理好的發出去,接著迴應 B 請求,完事兒以後再傳送 A 請求中剩下的部分。

像這樣雙向,實時的通訊,就叫做多工(Multiplexing)。

5.3 資料流

HTTP/2 的資料包不是按照順序傳送的,同一個連線裡的資料包可能屬於多個請求。所以需要一個編號,這個編號指明資料包屬於哪一個請求或者回應。

這裡有一個概念叫做資料流,我們把一個請求或者回應的所有資料包合在一起稱為一個資料流。每個資料流都有一個獨一無二的編號,資料包傳送的時候都必須標定資料流編號。

客戶端請求的資料流編號一律為基數,而服務端迴應的資料流編號為偶數。

在 HTTP/1.1 中終止請求的方式只能是關閉 TCP 連線,而現在可以傳送一個訊號:(RST_STREAM 幀),取消這個資料流。

也就是說 HTTP/2 可以取消某一次請求,同時能保證 TCP 連線開啟,可以被其他請求所使用。

此外,客戶端可以指定資料流的優先順序,優先順序高的伺服器越早響應。

5.4 頭資訊壓縮

因為協議不帶有狀態,每次請求都必須附上所有資訊。有一些資訊是重複的,這樣會影響資料傳輸速度,浪費頻寬。

HTTP/2 採用頭資訊壓縮機制可以減少不利影響。首先是將資訊壓縮後再傳送(gzip 或者 compress),其次是客戶端 和伺服器同時維護一張頭資訊表,這個表很神奇的地方在於可以利用索引進行管理,只要我們傳送索引就可以表示我們傳輸的資訊,這樣就能夠提高速度。

5.5 主動推送

HTTP/2 允許伺服器在沒有經過允許的情況下,可以主動向客戶端推送資源 。這個過程叫做伺服器推送(server push)。

舉一個例子,別傳送郵件給我們的時候,郵箱會冒個彈框出來告訴我們有人往郵箱裡投遞了一封郵件。注意,此時我們並沒有重新整理網頁。

伺服器推送還可能用到訊息提醒,靜態資源自動推送到服務端等場景。

相關文章