SERVER PUSH的具体实现    
      来源:[email protected] 
   
  
                      SERVER PUSH的具体实现     拙作“推”向更快发表后,笔者收到了很多朋友的来信,希望能了解更多的 关于 SERVER PUSH的技术资料,说实话对这一新技术笔者也不是太了解,但本着 知无不言的思想,在这里根据笔者的实际使用情况作一些详细的介绍,希望给那 些对 SERVER PUSH有兴趣的朋友一点点的帮助和参考。也希望能借此抛砖引玉, 求得高手的不吝指教。 
     
    “推”由于篇幅的原因,只对 SERVER PUSH作了一般的介绍,下面我们来看 看SERVER PUSH的具体实现过程: 
    一、作业系统: 
    目前 SERVER PUSH还不能在WIN9X上实现,至少是我自己还没有在WIN9X作为 主机上实现过这一功能。经笔者试验成功的作业系统有:WINNT4.0,UNIX,LINUX, FREEBSD,以LINUX支持最好。因为我使用的LINUX都是最新的版本,可以方便地 编译最新的功能模块。当然还有其它的作业系统也能很好地支持 SERVER PUSH功 能,但笔者限于条件没有测试过。 
    二、WWW服务器: 
    其实目前除了IIS和APACHE这两个WWW服务器,你没有更好的选择,值得庆辛 的是它们都能很好地支持 SERVER PUSH,当然你应该选择它们的最新版。别的那 些小孩子过家家那样的WWW服务器就不用试了。在这里笔者极力推荐在LINUX上安 装APACHE,以便能自由编译功能模块,这样可以充分使用SERVER PUSH、FASTCGI 
、 
E-CGI、PHP等新的扩展功能。 
    三、脚本支持: 
    虽然 SERVER PUSH可以用更多的脚本程序来编写,但笔者强烈推荐用PERL或 C语言来写CGI脚本,因为PERL已经是CGI脚本程序事实上的标准。而且在PERL5中 已经可以直接调用C子程序而不需要任何声明。不管你用什么语言来写CGI脚本, 解释器中应该有CGI.PM模块,笔者试用的版本是 5.004,这一模块的更新版大家 可以从网上下载,找不到?用搜索引擎输入CGI.PM就行了,要多少个都有。 
    好了,有了上面的工具,下面我们就来写一个 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),"\n", 
    multipart_end; 
    sleep 1; 
  } 
    use CGI qw/:push -nph/;这一行告诉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最根本的方 法类型:Content-Type: multipart/x-mixed-replace; boundary='--boundary' 如果你对HTTP的MIME类型有详细的了解,你就知道multipart类型是一种复合类 型,它的子类型是mixed,子类型的X参数大家可以参看详细的MIME类型说明,这 里最关键的是replace方法,它不停地用新接收的数据更新旧的数据。这,就是 SERVER  PUSH最大的技术内涵。boundary只是一个边界值,告诉浏览器从这儿开 始,使用SERVER  PUSH方法了。其实你完全可以这样理解,只要在脚本程序中声 明了multipart/x-mixed-replace; boundary='--boundary'这样一个文档类型, 服务器就和客户机建立了一个特别的连结。服务器就不断地把客户机请求的数据 源源不断地推向了客户机。而传统的CLIENT PULL方法是:1、CLIENT和SERVER建 立连结。2、CLIENT发送请求。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'\n\ 
n" 
这样做的好处是当系统不能支持multipart_init()涵数时,就可以直接这样声明 
。 
    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'} = "\n--$boundary\n"; 
    $type = SERVER_PUSH($boundary); 
    return $self->header( 
-nph => 1, 
-type => $type, 
(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(@_); 
    return $self->{'separator'};   
    }   
    其它的在使用SERVER PUSH时的一些技巧,限于篇幅我不能再作过多的介绍, 大家可以到下面地址看看我用SERVER PUSH写的聊天室,欢迎有兴趣的朋友和我交 流。 
    聊天室地址:http://wangjh.3322.net/chat.htm,保密哦,这是一个免费个 人主页空间,不让放聊天室,网管知道了就会DEL了的。:( 
     
  --------------------------------------------------------------------------------  编辑整理:中国PHP自由联盟 
  [关闭窗口] - 2000-05-08 - 
    
 Copyright ? 2000 Chinese PHP Power All rights reserved.