一、Content-Length
1.1 內容校驗的方式
對於http的請求返回結果要進行內容的長度校驗主要有兩種方式,二者互斥使用
-
- 1、客戶端在http頭(head)加Connection:keep-alive時,服務器的response是Transfer-Encoding:chunked的形式,通知頁面數據是否接收完畢,例如長連接或者程序運行中可以動態的輸出內容,例如一些運算比較復雜且需要用戶及時的得到最新結果,那就采用chunked編碼將內容分塊輸出。
- 2、除了如1所述之外的情況一般都是可以獲取到Content-Length的。
1.2 Content-Length概念
在HTTP協議中,Content-Length用於描述HTTP消息實體的傳輸長度the transfer-length of the message-body。在HTTP協議中,消息實體長度和消息實體的傳輸長度是有區別,比如說gzip壓縮下,消息實體長度是壓縮前的長度,消息實體的傳輸長度是gzip壓縮后的長度。
“The entity-length of a message is the length of the message-body before any transfer-codings have been applied”。也就是有chunk就不能有content-length 。
1.3 Content-Length獲取規則
- 1、響應為1xx,204,304相應或者head請求,則直接忽視掉消息實體內容。
- 2、如果有Transfer-Encoding,則優先采用Transfer-Encoding里面的方法來找到對應的長度。比如說Chunked模式,就通過chunk機制來處理這種情況。HTTP1.1必須支持chunk模式。因為當不確定消息長度的時候,可以通過chunk機制來處理這種情況。也就是動態發送數據,而不是一次性將所有數據全部發送過來,所以每次發送的數據的長度大小需要發送時才能確定,此時,即使設置了Content-Length也會被忽略。
- 3、“如果head中有Content-Length,那么這個Content-Length既表示實體長度,又表示傳輸長度。如果實體長度和傳輸長度不相等(比如說設置了Transfer-Encoding),那么則不能設置Content-Length。如果設置了Transfer-Encoding,那么Content-Length將被忽視”。這句話翻譯的優點饒,其實關鍵就一點:有了Transfer-Encoding,則不能有Content-Length。獲取長度后,就可以根據長度獲取報文,然后判斷是否進行了壓縮,也就是Content-Enconding字段。
- 4、Range傳輸。不關注,沒詳細看了:)
- 5、通過服務器關閉連接能確定消息的傳輸長度。(請求端不能通過關閉連接來指明請求消息體的結束,因為這樣可以讓服務器沒有機會繼續給予響應)。這種情況主要對應為短連接,即非keep-alive模式。主要是在HTTP1.1版本之前。
二、chunk機制
2.1 chunked編碼
2.1.1 概念
分塊傳輸編碼(Chunked transfer encoding)是只在HTTP協議1.1版本(HTTP/1.1)中提供的一種數據傳送機制。以往HTTP的應答中數據是整個一起發送的,並在應答頭里Content-Length字段標識了數據的長度,以便客戶端知道應答消息的結束。
2.1.2 優點
- 對於動態生成的應答內容來說,內容在未生成完成前總長度是不可知的。因此需要先緩存生成的內容,再計算總長度填充到Content-Length,再發送整個數據內容。這樣顯得不太靈活,而使用分塊編碼則能得到改觀。
- 分塊傳輸編碼允許服務器在最后發送消息頭字段。例如在頭中添加散列簽名。
- 對於壓縮傳輸傳輸而言,可以一邊壓縮一邊傳輸。
2.1.3 格式
如果在http的消息頭里Transfer-Encoding為chunked,那么就是使用此種編碼方式。接下來會發送數量未知的塊,每一個塊的開頭都有一個十六進制的數,表明這個塊的大小,然后接CRLF("\r\n")。然后是數據本身,數據結束后,還會有CRLF兩個字符。有一些實現中,塊大小的十六進制數和CRLF之間可以有空格。
最后一塊的塊大小為0,表明數據發送結束。最后一塊不再包含任何數據,但是可以發送可選的尾部,包括消息頭字段。消息最后以CRLF結尾。
2.2 實戰
抓包截圖:
2.3 測試
如何測試自己的程序支持接收這種編碼方式的數據呢?第一想到的當然是配下服務器,使其固定以這種方式發數據,但是沒有搜索到如果把apache配成這個模式。好在強大的Stack Overflow里找到了有用信息。
http://www.httpwatch.com/httpgallery/chunked/chunkedimage.aspx 這個頁面就是chunked編碼傳輸的。只需要測試看能否正確下載這個頁面就可以了,分塊發送時服務器是每0.1s發送1k的數據過來。
三、轉載文章
https://leon-liu.blog.csdn.net/article/details/53432408?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-13.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-13.control