文章版权归原作者所有! (www.MegaEntry.com)
一、环境配置 为了在Linux下更充分领略Server Push的功能,在运行环境上,我们需进行一些选择。 1.WWW服务器 首先要在Linux上安装Apache,以便能自由编译功能模块,这样可以充分使用Server Push、FastCGI、EPerl和PHP等新的扩展功能。 2.脚本支持 笔者推荐用Perl或C语言来写CGI脚本,因为Perl已经是CGI脚本程序事实上的标准。而且在Perl 5中已经可以直接调用 C子程序而不需要任何声明。不管你用什么语言来写CGI脚本,解释器中应该有CGI.PM模块,笔者试用的版本是 5.004,这一模块的更新版大家可以从网上下载。 二、程序实例及函数剖析MegaEntry 网络社区与信息交流平台!
好了,有了上面的工具,下面我们就来写一个Server Push程序来说明它的实现过程: #!/usr/bin/perl use CGI qw/:push -nph/; $| = 1; print multipart―init(-boundary=〉′--boundary′); while (1) { print multipart―start(-type=〉′text/plain′), ″The current time is ″,scalar(localtime),″ ″, multipart―end; sleep 1; } 程序第二行告诉CGI解释程序来调用支持Server Push 的功能模块(CGI.PM),在这个模块中预先定义了三个函数:multipart―init()、multipart―start()和multipart―end,只要在程序中有use CGI qw/:push -nph/声明,就可以直接使用这三个函数。 multipart―init()函数的作用是声明一个文档类型,就像普通的CGI程序中的“Content-Type: text/html”声明,告诉服务器下面传送的是HTML文档,而multipart―init()这一函数声明的文件类型却是实现Server Push最根本的方法类型:MegaEntry 网络社区与信息交流平台!
Content-Type: multipart/x-mixed-replace; boundary=′--boundary′ 如果你对HTTP的MIME类型有详细的了解,你就知道multipart 类型是一种复合类型,它的子类型是mixed,子类型的X参数,大家可以参看详细的MIME类型说明,这里最关键的是replace方法,它不停地用新接收的数据更新旧的数据,这就是 Server Push最大的技术内涵。boundary只是一个边界值,告诉浏览器从这儿开始,使用Server Push方法了。其实你完全可以这样理解,只要在脚本程序中声明了如multipart/x-mixed-replace 这样一个文档类型,服务器就和客户机建立了一个特别的连接。服务器就不断地把客户机请求的数据源源不断地推向了客户机。而传统的 Client PULL方法则是: 1.Client 和Server建立连接 2.Client发送请求到Server 3.Server响应请求 4.Server 断开连接以响应下一请求。 通过这两种方法的比较,大家可以看出Server Push优点主要在于服务器和客户机之间这种不间断的连接方式,使它不需要采用Client PULL的〈META http-equiv=refresh content=″n″〉这种方法来刷新页面,不仅更新速度快,而且不会产生闪动效果。 如果你不用multipart―init()而直接在脚本程序中用以下语句也可以达到同样目的:print ″Content-Type: multipart/x-mixed-replace; boundary=′boundary′ ″。当系统不支持multipart―init()函数时,就可以直接这样声明。MegaEntry 网络社区与信息交流平台!
multipart―start() 这个函数是为服务器指定了传送一个确定的文档,如果不用这个函数,根据脚本程序的内容服务器可以直接把指定数据传送给客户机,当然客户机不能识别这种类型的文档可以忽略而不会产生错误。但如果你指明了具体的文档类型,如例程中的text/plain(纯文本类型),客户机就不再对文档加以分析,从而提高了处理速度,否则客户机只知道传送过来的是 multipart(复合型)而要重新对其分析。 至于multipart―end函数不需作详细说明,只是说明了一个 Push过程的结束。 为了使大家能更好地理解这三个函数详细的技术内容,笔者把这三个函数的实现过程介绍给大家: sub multipart―init { my($self,@p) = self―or―default(@―); my($boundary,@other) = $self-〉rearrange([BOUNDARY],@p); $boundary = $boundary || ′------- =―aaaaaaaaaa0′; $self-〉{′separator′} = ″ --$boundary ″; $type = Server―Push($boundary); return $self-〉header( -nph =〉 1, -type =〉 $type,文章版权归原作者所有! (www.MegaEntry.com)
(map { split ″=″, $―, 2 } @other), ) . $self-〉multipart―end; } sub multipart―start { my($self,@p) = self―or―default(@―); my($type,@other) = $self-〉rearrange([TYPE],@p); $type = $type || ′text/html′; return $self-〉header( -type =〉 $type, (map { split ″=″, $―, 2 } @other), ); } sub multipart―end { my($self,@p) = self―or―default(@―);文章版权归原作者所有! (www.MegaEntry.com)
return $self-〉{′separator′}; } 三、应用技巧 使用Server Push的其它技巧,限于篇幅,笔者不再作过多的介绍。不过有时由于客户机在一段时间内没有对服务器发生请求,也就是若一段时间内没有新的内容向浏览器输入,可能发生连接超时现象,用下面的程序来处理一下就能很好地解决: $message=1; $whilecount=1; do { 主程序;文章版权归原作者所有! (www.MegaEntry.com)
$message++; } if ($whilecount == 30) { print ″〈SCRIPT〉$message〈/SCRIPT〉 15 12″; $whilecount = 0; } $whilecount++;文章版权归原作者所有! (www.MegaEntry.com)
sleep 1; 这种技巧大家一看就明白了,正如很多 FTP软件的Loop一样,在空闲时发一个空信号,不让程序进入等待状态。这段程序每过30秒就给客户机输出一行〈SCRIPT〉$message〈/SCRIPT〉,而$message是数值1、2、3等,这一行在浏览器浏览时并不显示任何内容,让浏览者感觉不到。