一般情況HTTP的Header包含Content-Length域來指明報文體的長度。
有時候服務生成HTTP回應是無法確定消息大小的,比如大文件的下載,或者后台需要復雜的邏輯才能全部處理頁面的請求,這時用需要實時生成消息長度,服務器一般使用chunked編碼。采用chunked編碼有兩種選擇,一種是設定Server的IO buffer長度讓Server自動flush buffer中的內容,另一種是手動調用IO中的flush函數。不同的語言IO中都有flush功能:
- php: ob_flush(); flush();
- perl: STDOUT->autoflush(1);
- java: out.flush();
- python: sys.stdout.flush()
- ruby: stdout.flush
使用chunked編碼的Headers如下(可以利用FireFox的FireBug插件或HttpWatch查看Headers信息,HttpWatch還可以查看chunked的個數):
![20ccda3a01d27c82399000cab7e91c11.png](https://img8.php1.cn/3cdc5/12945/978/ab04536edb62b4fb.png)
Chunked編碼一般使用若干個chunk串連而成,最后由一個標明長度為0的chunk標示結束。每個chunk分為頭部和正文兩部分,頭部內容指定下一段正文的字符總數(非零開頭的十六進制的數字)和數量單位(一般不寫,表示字節).正文部分就是指定長度的實際內容,兩部分之間用回車換行(CRLF)隔開。在最后一個長度為0的chunk中的內容是稱為footer的內容,是一些附加的Header信息(通常可以直接忽略)。
上述解釋過於官方,簡而言之,chunked編碼的基本方法是將大塊數據分解成多塊小數據,每塊都可以自指定長度,其具體格式如下(BNF文法):
Chunked-Body = *chunk //0至多個chunk
last-chunk //最后一個chunk
trailer //尾部
CRLF //結束標記符
chunk = chunk-size [ chunk-extension ] CRLF
chunk-data CRLF
chunk-size = 1*HEX
last-chunk = 1*("0") [ chunk-extension ] CRLF
chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)
trailer = *(entity-header CRLF)
解釋:
Chunked-Body表示經過chunked編碼后的報文體。報文體可以分為chunk, last-chunk,trailer和結束符四部分。chunk的數量在報文體中最少可以為0,無上限;
每個chunk的長度是自指定的,即,起始的數據必然是16進制數字的字符串,代表后面chunk-data的長度(字節數)。這個16進制的字符串第一個字符如果是“0”,則表示chunk-size為0,該chunk為last-chunk,無chunk-data部分。
可選的chunk-extension由通信雙方自行確定,如果接收者不理解它的意義,可以忽略。
trailer是附加的在尾部的額外頭域,通常包含一些元數據(metadata, meta means "about information"),這些頭域可以在解碼后附加在現有頭域之后
![b7f0599c0886ea1debe7f2822cf8b501.gif](https://img8.php1.cn/3cdc5/12945/978/0960fd71e8bc6fba.jpeg)
看一個wireshark抓包的結果:
![f5cd779a64e58c8de4ed6f2937767291.png](https://img8.php1.cn/3cdc5/12945/978/b3462d2fcee99a32.png)
這里面只有一個有意義的chunke以及一個footer。第一個chunk,頭部是3134這兩個字節,表示的是1和4這兩個ascii字符,被http協議解釋為十六進制數14,也就是十進制的20。后面緊跟0d0a,再接着是20個字節的chunk正文(圖中的011e~0131)。
后面再接着0d0a,然后就是footer了,30表示ascii字符0,http解釋為長度是0(也說明了這是最后一個chunk),后面緊跟0d0a,然后正文部分為空,再接0d 0a表示結束
轉載文章:
1)http://blog.csdn.net/zhangboyj/article/details/6236780
2)http://www.cnblogs.com/jhxk/articles/2715848.html
3)http://www.cnblogs.com/jhxk/articles/2715848.html