随笔-124  评论-194  文章-0  trackbacks-0

DWR2.0的推技术:这里有介绍

comet的实现介绍:这里

其中的原理在于维护HTTP长连接,这里有介绍

 

摘录一部分,说明其原理:

Pushlet基于HTTP流,这种技术常常用在多媒体视频、通讯应用中,比如QuickTime。与装载HTTP页面之后马上关闭HTTP连接的做法相反,Pushlet采用HTTP流方式将新数据源源不断地推送到client,再此期间HTTP连接一直保持打开。有关如何在Java中实现这种Keep-alive的长连接请参看Sun提供的《HTTP Persistent Connection》W3C的《HTTP1.1规范》。
示例1
        我们利用HTTP流开发一个JSP页面(因为它易于部署,而且它在web server中也是作为servlet对待的),此页面在一个定时器循环中不断地发送新的HTML内容给client:


<%
  int i = 1;
    
  try {
    while (true) {
       out.print("<h1>"+(i++)+"</h1>");
       out.flush();
      
       try {
            Thread.sleep(3000);
       } catch (InterruptedException e) {
       out.print("<h1>"+e+"</h1>");
        }
     }
   } catch (Exception e) {
       out.print("<h1>"+e+"</h1>");
   }
%>

        在Pushlet源代码中提供了此页面(examples/basics/push-html-stream.jsp)。上面的页面并不是十分有用,因为在我们刷新页面时,新内容机械地、持续不断地被添加到页面中,而不是server端更新的内容。
示例2
        现在让我们步入Pushlet工作机理中一探究竟。通过运行Pushlet的示例源代码(examples/basics/ push-js-stream.html),我们会看到这个每3秒刷新一次的页面。那么它是如何实现的呢?
        此示例中包含了三个文件:push-js-stream.html、push-js-stream-pusher.jsp、push-js-stream-display.html。
        其中push-js-stream.html是主框架文件,它以HTML Frame的形式包含其它两个页面。
        push-js-stream-pusher.jsp是一个JSP,它执行在server端,此文件内容如下:

  7: <%
  8:   /** Start a line of JavaScript with a function call to parent frame. */
  9:   String jsFunPre = "<script language=JavaScript >parent.push('";
10:  
11:   /** End the line of JavaScript */
12:   String jsFunPost = "')</script> ";
13:  
14:   int i = 1;
15:   try {
16:  
17:     // Every three seconds a line of JavaScript is pushed to the client
18:     while (true) {
19:    
20:        // Push a line of JavaScript to the client
21:        out.print(jsFunPre+"Page "+(i++)+jsFunPost);
22:        out.flush();
23:        
24:        // Sleep three secs
25:        try {
26:             Thread.sleep(3000);
27:        } catch (InterruptedException e) {
28:             // Let client display exception
29:             out.print(jsFunPre+"InterruptedException: "+e+jsFunPost);
30:        }
31:      }
32:    } catch (Exception e) {
33:             // Let client display exception
34:             out.print(jsFunPre+"Exception: "+e+jsFunPost);
35:    }
36: %>

注意在示例1和示例2中使用JSP时都存在一个问题:一些servlet引擎在某个client离开时会“吃掉”IOException,以至于JSP页面将永不抛出此异常。所以在这种情况下,页面循环将会永远执行下去。而这正是Pushlet实现采用servlet的原因之一:可以捕获到IOException。
        在上面代码的第21行中可以看到在一个定时器循环(3秒/周期)中打印了一些HTML并将它们输出到client浏览器。请注意,这里推送的并非HTML而是Javascript!这样做的意义何在?
        它把类似“<script language=JavaScript >parent.push('Page 4')</script>”的一行代码推送到浏览器;而具有JavaScript引擎的浏览器可以直接执行收到的每一行代码,并调用parent.push()函数。而代码中的Parent便是浏览器页面中所在Frame的Parent,也就是push-js-stream.html。让我们看看都发生了什么?

<script LANGUAGE="JavaScript">
var pageStart="<HTML><HEAD></HEAD><BODY BGCOLOR=blue TEXT=white><H2>Server pushes: <para>";
var pageEnd="</H2></BODY></HTML>";
  // Callback function with message from server.
  // This function is called from within the hidden JSP pushlet frame
  function push(content) {

    // Refresh the display frame with the content received
    window.frames['displayFrame'].document.writeln(pageStart+content+pageEnd);
    window.frames['displayFrame'].document.close();
  }

</script>



     <!-- frame to display the content pushed by the pushlet -->
    
    
     <!-- Hidden frame with the pushlet that pushes lines of JavaScript-->
    
</FRAMESET>

        可以看到push-js-stream.html中的push()函数被名为pushletFrame的JSP Frame调用:把传入的参数值写入到displayFrame(此Frame为push-js-stream-display.html)。这是动态HTML的一个小技巧:使用document对象的writeln方法刷新某个Frame或者Window的内容。
        于是displayFrame成为了用于显示内容的、真正的视图。displayFrame初始化为黑色背景并显示“wait…”直到来自server的内容被推送过来:

<H1>WAIT...</H1>

        这便是Pushlet的基本做法:我们从servlet(或者从示例中的JSP)把JavaScript代码作为HTTP流推送到浏览器。这些代码被浏览器的JavaScript引擎解释并完成一些有趣的工作。于是便轻松地完成了从server端的Java到浏览器中的JavaScript的回调。
        上面的示例展示了Pushlet原理,但这里存在一些等待解决的问题和需要增添的特性。于是我建立了一个小型的server端Pushlet框架(其类结构图表将会展示在下面),添加了一些用在client中的JavaScript库。由于client需要依赖更多的DHTML特性(比如Layers),我们将首先粗略地温习一些DHTML知识。示例代码见examples/dhtml。
posted on 2007-07-03 18:10 我爱佳娃 阅读(2290) 评论(0)  编辑  收藏 所属分类: web技术

只有注册用户登录后才能发表评论。


网站导航: