您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關HTTP的傳輸編碼是什么,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
傳輸編碼在 HTTP 的報文頭中,使用 Transfer-Encoding
首部進行標記,它就是指明當前使用的傳輸編碼。
Transfer-Encoding
會改變報文的格式和傳輸的方式,使用它不但不會減少內容傳輸的大小,甚至還有可能會使傳輸變大,看似是一個不環保的做法,但是其實是為了解決一些特殊問題。
簡單來說,傳輸編碼必須配合持久連接去使用,為了在一個持久連接中,將數據分塊傳輸,并標記傳輸結束而設計的,后面會詳細講解。
在早年間的設計里,和內容編碼使用 Accept-Encoding
來標記客戶端接收的壓縮編碼類型一樣,傳輸編碼還需要配合 TE
這個請求報文頭來使用,用于指定支持的傳輸編碼。但是在最新的 HTTP/1.1 協議規范中,只定義了一種傳輸編碼:分塊編碼(chunked),所以并不需要再依賴 TE
這個頭部。
這些細節,后面都會講到。既然傳輸編碼和持久連接是息息相關的,那我們就先來了解一下什么是持久連接。
持久連接通俗來講,就是長連接,英文叫 Persistent Connection,其實按字面意思理解就好了。
在早期的 HTTP 協議中,傳輸數據的順序大致分為發起請求、建立連接、傳輸數據、關閉連接等步驟,而持久連接,就是去掉關閉連接這個步驟,讓客戶端和服務端可以繼續通過此次連接傳輸內容。
這其實也是為了提高傳輸效率,我們知道 HTTP 協議是建立在 TCP 協議之上的,自然有 TCP 一樣的三次握手、慢啟動等特性,這樣每一次連接其實都是一次寶貴的資源。為了盡可能的提高 HTTP 的性能,使用持久連接就顯得很重要了。為此在 HTTP 協議中,就引入了相關的機制。
在早期的 HTTP/1.0 協議中并沒有持久連接,持久連接的概念是在后期才引入的,當時是通過 Connection:Keep-Alive
這個頭部來標記實現,用于通知客戶端或服務端相對的另一端,在發送完數據之后,不要斷開 TCP 連接,之后還需要再次使用。
而在 HTTP/1.1 協議中,發現持久連接的重要性了,它規定所有的連接必須都是持久的,除非顯式的在報文頭里,通過 Connection:close
這個首部,指定在傳輸結束之后會關閉此連接。
實際上在 HTTP/1.1 中Connect
這個頭部已經沒有 Keep-Alive
這個取值了,由于歷史原因,很多客戶端和服務端,依然保留了這個報文頭。
長連接帶來了另外一個問題,如何判定當前數據發送完成。
在早期不支持持久連接的時候,其實是可以依靠連接斷開來判定當前傳輸已經結束,大部分瀏覽器也是這么干的,但這并不是規范的操作。應該使用 Content-Length
這個頭部,來指定當前傳輸的實體內容長度。
下面舉個例子,在保持持久連接的情況下,依賴 Content-Length
來確定數據發送完畢。
Content-Length
在這里起到了一個響應實體已經發送結束的判斷依據。這樣的情況下,我們就要求 Content-Length
必須和內容實體的長度一致,如果不一致,就會出現各種問題。
如上圖所示,如果 Content-Length
小于內容實體的長度,則會截斷,反之則無法判定當前響應已經結束,會將請求持續掛起造成 Padding 狀態。
理想情況下,我們在響應一個請求的時候,就需要知道它的內容實體的大小。但是在實際應用中,有些時候內容實體的長度并沒有那么容易獲得。例如內容實體來自網絡文件、或者是動態生成的。這個時候如果依然想要提前獲取到內容實體的長度,只能開一個足夠大的 Buffer,等內容全部緩存好了再計算。
但這并不是一個好的方案,全部緩存到 Buffer 里,第一會消耗更多的內存,第二也會更耗時,讓客戶端等待過久。
此時就需要一個新的機制,不依賴 Content-Length
的值,來判定當前內容實體是否傳輸完成,此時就需要 Transfer-Encoding
這個頭部來判定。
前面也提到,Transfer-Encoding
在最新的 HTTP/1.1 協議里,就只有 chunked
這個參數,標識當前為分塊編碼傳輸。
分塊編碼傳輸既然只有一個可選的參數,我們就只需要指定它為 Transfer-Encoding:chunked
,后續我們就可以將內容實體包裝一個個塊進行傳輸。
分塊傳輸的規則:
1. 每個分塊包含一個 16 進制的數據長度值和真實數據。
2. 數據長度值獨占一行,和真實數據通過 CRLF(\r\n) 分割。
3. 數據長度值,不計算真實數據末尾的 CRLF,只計算當前傳輸塊的數據長度。
4. 最后通過一個數據長度值為 0 的分塊,來標記當前內容實體傳輸結束。
在這個例子中,首先在響應頭部里標記了 Transfer-Encoding: chunked
,后續先傳遞了第一個分塊 “0123456780”,長度為 b(11 的十六進制),之后分別傳輸了 “Hello CxmyDev” 和 “123”,最后以一個長度為 0 的分塊標記當前響應結束。
chunked 的拖掛
當我們使用 chunked 進行分塊編碼傳輸的時候,傳輸結束之后,還有機會在分塊報文的末尾,再追加一段數據,此數據稱為拖掛(Trailer)。
拖掛的數據,可以是服務端在末尾需要傳遞的數據,客戶端其實是可以忽略并丟棄拖掛的內容的,這就需要雙方協商好傳輸的內容了。
在拖掛中可以包含附帶的首部字段,除了 Transfer-Encoding、Trailer 以及 Content-Length 首部之外,其他 HTTP 首部都可以作為拖掛發送。
一般我們會使用拖掛來傳遞一些在響應報文開始的時候,無法確定的某些值,例如:Content-MD5 首部就是一個常見的在拖掛中追加發送的首部。和長度一樣,對于需要分塊編碼傳輸的內容實體,在開始響應的時候,我們也很難算出它的 MD5 值。
注意這里在頭部增加了 Trailder
,用以指定末尾還會傳遞一個 Content-MD5 的拖掛首部,如果有多個拖掛的數據,可以使用逗號進行分割。
內容編碼和傳輸編碼一般都是配合使用的。我們會先使用內容編碼,將內容實體進行壓縮,然后再通過傳輸編碼分塊發送出去。客戶端接收到分塊的數據,再將數據進行重新整合,還原成最初的數據。
我們對傳輸編碼應該有一定的了解了。這里簡單總結一下:
1. 傳輸編碼使用 Transfer-Encoding 首部進行標記,在最新的 HTTP/1.1 協議里,它只有 chunked 這一個取值,表示分塊編碼。
2. 傳輸編碼主要是為了解決持久連接里將數據分塊傳輸之后,判定內容實體傳輸結束。
3. 分塊的格式:數據長度(16進制)+ 分塊數據。
4. 如果還有額外的數據,可以在結束之后,使用 Trailer
進行拖掛傳輸額外的數據。
5. 傳輸編碼通常會配合內容編碼一起使用。
此外,傳輸編碼應該是所有 HTTP/1.1 的標準實現,應該都有支持,如果收到無法理解的經過傳輸編碼的報文,應該直接返回 501 Unimplemented 這個狀態碼來回復即可。
以上就是HTTP的傳輸編碼是什么,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。