网上使用chunked编码的网站似乎并不是很多,除了那些使用gzip压缩的网站,例:google.com,还有就是大部分打开gzip压缩的php论坛。
; j/ ~- e0 b. A6 H3 a- d* q根据本人的理解,使用chunked编码的主要好处就在于一些程序的运算出过程中,可以动态的输出内容。
7 ?- w8 C+ Q" D/ v/ u例如,要在后台处理一个小时的运算,但又不希望用户等一个小时才能看到结果。这时就可采用chunked编码将内容分块输出,用户随时都可以接收到最新的处理结果。. ]- q; N7 i& ?6 t8 G) M
asp关闭了缓存的输出模式,就是chunked编码的。(response.buffer = false)9 B- e: z8 `2 k
而每一次的response.write,都是一个chunked,所以不要使用的太频繁哦,否则chunk数量太多,额外的数据太浪费空间了。& [. z$ s+ K6 \6 l2 `9 ^
若想了解chunked的具体编码结构,用asp关闭缓存调试蛮方便的。:)- r u. b: E2 s; ?7 @) b
我们先来看看rfc2616中对chunked的定义:
4 `. ^5 D/ U9 k7 [chunked-body = *chunk& N4 q J/ i/ H( l2 t2 O' _9 H# R
last-chunk
3 A9 D$ a4 c D: ^% [- Otrailer6 s* I' S3 F( X2 c+ ~4 M5 T% V: n
crlf
: E" @. z, ^5 S- \' [chunk = chunk-size [ chunk-extension ] crlf) R5 x6 p% p- O4 J o4 ]9 d$ _- U7 B
chunk-data crlf
/ A ]; U( a. k; P: vchunk-size = 1*hex
9 x5 m6 o9 R! i: }2 k) @! glast-chunk = 1*(0) [ chunk-extension ] crlf" d5 a& V0 Y/ \$ j6 I1 k% Y7 X, Q: M
chunk-extension= *( ; chunk-ext-name [ = chunk-ext-val ] ), q9 G% A) q, p \% E6 z
chunk-ext-name = token
2 ]- H# E g7 \$ cchunk-ext-val = token | quoted-string+ G# N9 |: x- z4 h O. c6 V5 O
chunk-data = chunk-size(octet)$ |0 U! d% M }. A6 ^$ p; ^7 G
trailer = *(entity-header crlf)! N' a% T- c" y) a' q$ l. S6 `: E
我们来模拟一下数据结构:' B5 |( y, O9 h* m& }6 J
[chunk大小][回车][chunk数据体][回车][chunk大小][回车][chunk数据体][回车][0][回车]8 R% J @+ M" a6 S' [5 `
注意chunk-size是以十六进制的ascii码表示的,比如86ae(实际的十六进制应该是:38366165),计算成长度应该是:34478,表示从回车之后有连续的34478字节的数据。$ p$ B* k0 _* L% H7 j
跟踪了的返回数据,发现在chunk-size中,还会多一些空格。可能是固定长度为7个字节,不满7个字节的,就以空格补足,空格的ascii码是0x20。
( l' w0 d, o" L9 Q- q4 Q" t- M以下是解码过程的伪代码:% \$ U) x/ {* h& ^! _3 h
length := 0//用来记录解码后的数据体长度% |1 P- w. k0 n4 R% g) k
read chunk-size, chunk-extension (if any) and crlf//第一次读取块大小4 U6 R& w& Z9 y: a6 \! E# Q/ t3 i( S
while (chunk-size > 0) {//一直循环,直到读取的块大小为0! Y, {- @1 R7 P! K0 r3 i6 }9 t
read chunk-data and crlf//读取块数据体,以回车结束
5 R4 t! S1 e' v# P3 _+ H0 [7 Lappend chunk-data to entity-body//添加块数据体到解码后实体数据
, k+ }- p( O& ^% {, hlength := length + chunk-size//更新解码后的实体长度5 c7 o$ p% d& E- @; }: `9 d
read chunk-size and crlf//读取新的块大小
0 }; o) ? `/ q' O- K! P7 C}2 ` U: l6 l, h+ V# A# `
read entity-header//以下代码读取全部的头标记7 b- s" E6 v: M7 C J' G5 W! z
while (entity-header not empty) {
0 E. M2 r+ H0 C1 Q' }; ]append entity-header to existing header fields2 z% c& Z" F" |$ [+ ?8 U: x
read entity-header
9 u t& L+ N$ F: h @% i}; P+ G% x. l$ V4 F0 [
content-length := length//头标记中添加内容长度4 f3 U" [# o4 i( R
remove chunked from transfer-encoding//头标记中移除transfer-encoding1 Y- L' Q6 `0 ]5 A2 a4 u
有空再研究一下gzip+chunked是如何编码的,估计是每个chunk块进行一次gzip独立压缩。2 c% d" j' u* @9 V
使用了chunked,自然会在性能上稍微打点折扣,因为比正常的数据体多出了一些额外的消耗。) H7 U, s3 Q9 t
但是有一些情况下,必需要使用分块输出,这也是不得已而为之.: f4 A: L9 U; M8 E& r5 S
5 p0 L" G1 x( D5 S# N+ V& s更多网页制作信息请查看: 网页制作 |
|