网上使用chunked编码的网站似乎并不是很多,除了那些使用gzip压缩的网站,例:google.com,还有就是大部分打开gzip压缩的php论坛。6 [7 M# q5 R! F% D# K+ g5 W5 L5 q5 V
根据本人的理解,使用chunked编码的主要好处就在于一些程序的运算出过程中,可以动态的输出内容。* L" c! M! Q3 F
例如,要在后台处理一个小时的运算,但又不希望用户等一个小时才能看到结果。这时就可采用chunked编码将内容分块输出,用户随时都可以接收到最新的处理结果。
8 ]! D7 t) ?0 D" qasp关闭了缓存的输出模式,就是chunked编码的。(response.buffer = false)/ }0 Z- X3 q( T2 x" z
而每一次的response.write,都是一个chunked,所以不要使用的太频繁哦,否则chunk数量太多,额外的数据太浪费空间了。2 ~9 X; j# \5 W4 J8 I! w4 E
若想了解chunked的具体编码结构,用asp关闭缓存调试蛮方便的。:)
; `0 _! Y* w3 C/ J我们先来看看rfc2616中对chunked的定义:: ]$ p, c! |/ z$ L1 d8 D. _
chunked-body = *chunk; J5 I1 N! |" ?" d3 m# K
last-chunk
# k3 ~8 T+ n3 l7 d" Ztrailer
! v. d7 D0 V! n. z+ T& h+ ?crlf2 E, X+ z; f. X5 j* p) v
chunk = chunk-size [ chunk-extension ] crlf6 x+ |; Z$ e- E1 \% N+ B
chunk-data crlf7 m' K S9 g$ \5 n; l
chunk-size = 1*hex: H0 v4 o9 D9 ]0 j j( K# v
last-chunk = 1*(0) [ chunk-extension ] crlf
7 i7 c9 h4 p5 c7 \* M' bchunk-extension= *( ; chunk-ext-name [ = chunk-ext-val ] )
h! ^" O C( V* X/ d1 [! g3 Rchunk-ext-name = token
, E$ z0 T$ g n& Z$ kchunk-ext-val = token | quoted-string
; b/ T4 z, ^: {8 O$ K9 lchunk-data = chunk-size(octet)
+ [% E0 H# @6 H. etrailer = *(entity-header crlf)& a7 ]( {3 {! a. z( Z+ C/ {
我们来模拟一下数据结构:; X `& W9 X! }$ B6 X6 L) C$ A8 e
[chunk大小][回车][chunk数据体][回车][chunk大小][回车][chunk数据体][回车][0][回车]
% Z) d% i. y( u7 N( v* m- i注意chunk-size是以十六进制的ascii码表示的,比如86ae(实际的十六进制应该是:38366165),计算成长度应该是:34478,表示从回车之后有连续的34478字节的数据。
/ P$ F: K3 Y+ g) O: n跟踪了的返回数据,发现在chunk-size中,还会多一些空格。可能是固定长度为7个字节,不满7个字节的,就以空格补足,空格的ascii码是0x20。
}. R" q0 k1 ]$ p! q以下是解码过程的伪代码:
; A& e; E/ I6 z4 y" T! Mlength := 0//用来记录解码后的数据体长度
- X) p# \9 w8 u: f8 J! M4 x' Gread chunk-size, chunk-extension (if any) and crlf//第一次读取块大小3 R6 p) d8 P: t9 E4 X2 M
while (chunk-size > 0) {//一直循环,直到读取的块大小为0) A; b" I) q" H. p% J' l& E
read chunk-data and crlf//读取块数据体,以回车结束& e$ E. P" B8 D3 G; R
append chunk-data to entity-body//添加块数据体到解码后实体数据
$ U! q7 H P- |8 V6 [2 r' S6 Ulength := length + chunk-size//更新解码后的实体长度3 [ S7 G6 p. C" B" F
read chunk-size and crlf//读取新的块大小5 ^7 X3 S' r, I9 q& c9 K
}
2 P8 n4 u+ l$ W% b" m( W, Pread entity-header//以下代码读取全部的头标记6 Z. g# a5 P; W2 r3 x+ t
while (entity-header not empty) {
( X; C5 R9 c( o. @) Vappend entity-header to existing header fields3 f: P" }' i% }4 q$ Q8 K
read entity-header
( v" z& \1 v: s4 d4 e}9 @3 C# L" c, W" j) R
content-length := length//头标记中添加内容长度
' {* c: ~; p, D& zremove chunked from transfer-encoding//头标记中移除transfer-encoding4 O8 B1 f# w% ]! m0 U
有空再研究一下gzip+chunked是如何编码的,估计是每个chunk块进行一次gzip独立压缩。1 V; V, _& X) U8 v
使用了chunked,自然会在性能上稍微打点折扣,因为比正常的数据体多出了一些额外的消耗。
/ n5 p, w, i, ?+ I但是有一些情况下,必需要使用分块输出,这也是不得已而为之.9 \7 f$ g H+ p
* x/ L; @/ B. V: ?9 e6 U
更多网页制作信息请查看: 网页制作 |
|