进行Chunked编码传输的HTTP Response会在消息头部设置:
Transfer-Encoding: chunked
表示Content Body将用Chunked编码传输内容。
Chunked编码使用若干个Chunk串连而成,由一个标明长度为0的chunk标示结束。每个Chunk分为头部和正文两部分,头部内容指定下一段正文的字符总数(十六进制的数字)和数量单位(一般不写),正文部分就是指定长度的实际内容,两部分之间用回车换行(CRLF)隔开。在最后一个长度为0的Chunk中的内容是称为footer的内容,是一些附加的Header信息(通常可以直接忽略)。具体的Chunk编码格式如下:
Chunked-Body = *chunk
"0" CRLF
footer
CRLF
chunk = chunk-size [ chunk-ext ] CRLF
chunk-data CRLF
hex-no-zero =
chunk-size = hex-no-zero *HEX
chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)
footer = *entity-header
RFC文档中的Chunked解码过程如下:
length := 0
read chunk-size, chunk-ext (if any) and CRLF
while (chunk-size > 0) {
read chunk-data and CRLF
append chunk-data to entity-body
length := length + chunk-size
read chunk-size and CRLF
}
read entity-header
while (entity-header not empty) {
append entity-header to existing header fields
read entity-header
}
Content-Length := length
Remove "chunked" from Transfer-Encoding
最后提供一段PHP版本的chunked解码代码:
$chunk_size = (integer)hexdec(fgets( $socket_fd, 4096 ) );
while(!feof($socket_fd) && $chunk_size > 0) {
$bodyContent .= fread( $socket_fd, $chunk_size );
fread( $socket_fd, 2 ); // skip /r/n
$chunk_size = (integer)hexdec(fgets( $socket_fd, 4096 ) );
}
==========================================================
Server Push技术
服务器推送(Server Push)的思想是由服务器主动发送信息,并与客户端保持连接,直至服务器或客户端有一方自行中断连接为止。
Server Push的优点在于减少了建立、销毁连接的时间,去除了无用的页面刷新,缺点是占用了大量端口和相关系统资源,单纯的Server Push无法支持大用户量的服务。
Server Push使用了multipart/x-mixed-replace这种MIME类型,报文范例格式如下:
Content-type:multipart/x-mixed-replace;boundary=ThisRandomString
–ThisRandomString
Content-type:text/plain
第一个对象的数据
–ThisRandomString
Content-type:text/plain
第二个(最后一个)对象的数据
–ThisRandomString–
每个数据块由三部分组成:一是Content-type之类的头标,二是数据正文,三是报文边界,每当客户端接收到新的头标时,原有文档将被清除,并被新的数据块填充。
Apache和IIS均支持Server Push技术,笔者推荐Linux/Unix下的Apache软件,它可以自由的增删相应模块,以满足较多连接状态下的高性能需求。
===========================================
PHP-Push技术实现刷新功能
Server push 前一段时间炒得很热的“推”技术,不过网上大部分都是cgi的资料,偶尔看到一个法国的网站上有这么个介绍,可惜法语看不懂,只能从他的程序中看懂点东西,现整理个例子出来大家学习一下。可以用于聊天室的数据传输、网站上的新闻更新、等等各类更新频繁的页面。
以前做刷新主要通过页面上加标签。
< META HTTP-EQUIV=REFRESH CONTENT="time;URL=url" > |
img.php < ?php set_time_limit(0); $file = "./1.jpg"; $sep = "gIrLsKiCkAsSiTsAySsOoNaTsHiRt"; if(ereg(".*MSIE.*",$HTTP_SERVER_VARS["HTTP_USER_AGENT"])){ //如果是ie浏览器,直接输出就退出,IE的不支持哦,我没试出来过 header("Cache-Control: no-cache"); header("Pragma: no-cache"); header("Content-type: image/jpeg"); header("Content-size: " . filesize($file)); readfile($file); }else{ header("Content-Type: multipart/x-mixed-replace; boundary=$sep"); //这里是关键哦,看看MIME类型说明 //你会明白 print "--$sep "; do{ print "Content-Type: image/jpeg "; readfile($file); print " --$sep "; flush(); $mt = filemtime($file); do{ sleep (1); clearstatcache(); }while($mt == filemtime($file)); }while(1); } ? > |
http://www.zeali.net/entry/129
http://www.rainway.org/2004/10/03/server-push/
http://tech.ccidnet.com/art/294/20030212/37827_1.html