zoukankan      html  css  js  c++  java
  • 传说中的comet(iframe版)?

    comet有两种实现方式:长轮询(long-polling)和iframe流(streaming)。

    demo下载:comet-iframe.zip

    comet相关资料:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/

    之前一篇随笔已经写了长轮询的代码,虽然不知道那是不是就是正确的,因为我感觉就像是普通的ajax,这里写的就是iframe流的方式。

    前端代码:

    View Code
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>Comet demo</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript">
    var comet = {
    connection :
    false,
    iframediv :
    false,
    timer :
    0,
    initialize:
    function() {
    if (!-[1,]) {
    // For IE browsers
    comet.connection = new ActiveXObject("htmlfile");
    comet.connection.open();
    comet.connection.write(
    "<html>");
    comet.connection.write(
    "<script>document.domain = '"+document.domain+"'");
    comet.connection.write(
    "</html>");
    comet.connection.close();
    comet.iframediv
    = comet.connection.createElement("div");
    comet.connection.appendChild(comet.iframediv);
    comet.connection.parentWindow.comet
    = comet;
    comet.iframediv.innerHTML
    = "<iframe id='comet_iframe' name='comet_iframe' src='./backend.php'></iframe>";
    var comet_iframe = comet.connection.getElementById("comet_iframe");
    comet.timer
    = window.setInterval(function(){
    if(comet_iframe.readyState === "complete"){
    comet_iframe.src
    = comet_iframe.src;
    }
    },
    1000*65)
    }
    else{
    comet.connection
    = document.createElement('iframe');
    comet.connection.onload
    = function(){
    comet.connection.src
    = comet.connection.src;
    }
    comet.connection.setAttribute(
    'id','comet_iframe');
    comet.connection.setAttribute(
    'src','./backend.php');
    comet.connection.style.display
    = "none";
    document.body.appendChild(comet.connection);
    }
    },
    // this function will be called from backend.php
    printServerTime: function (time) {
    document.getElementById(
    'content').innerHTML = time;
    },
    onUnload:
    function() {
    if (comet.connection) {
    comet.connection
    = false; // release the iframe to prevent problems with IE when reloading the page
    }
    }
    }
    window.onload
    = function(){
    comet.initialize();
    }
    window.onbeforeunload
    = function(){
    comet.onUnload();
    }
    </script>
    </head>
    <body>
    <div id="content">The server time will be shown here</div>
    </body>
    </html>

    后台代码:

    View Code
    <?php

    header("Cache-Control: no-cache, must-revalidate");
    header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
    flush();

    ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>Comet php backend</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>

    <script type="text/javascript">
    // KHTML browser don't share javascripts between iframes
    var is_khtml = navigator.appName.match("Konqueror") || navigator.appVersion.match("KHTML");
    if (is_khtml)
    {
    var prototypejs = document.createElement('script');
    prototypejs.setAttribute(
    'type','text/javascript');
    prototypejs.setAttribute(
    'src','prototype.js');
    var head = document.getElementsByTagName('head');
    head[
    0].appendChild(prototypejs);
    }
    // load the comet object
    var comet = window.parent.comet;
    </script>

    <?php

    while(1) {
    echo '<script type="text/javascript">';
    echo 'comet.printServerTime('.time().');';
    echo '</script>';
    flush(); // used to send the echoed data to the client
    sleep(1); // a little break to unload the server CPU
    }

    ?>
    </body>
    </html>

    就像资料里所说的,“在 HTML 页面里嵌入一个隐蔵帧,然后将这个隐蔵帧的 SRC 属性设为对一个长连接的请求,服务器端就能源源不断地往客户端输入数据”,通过iframe里的内容进行长时间的请求,当需要传输内容时通过调用父页面js方法来实现页面展示,以此达到comet所需要的效果。

    使用iframe流的一个不足就是在IE、opera、chrome浏览器下,始终会显示下载没完成,并且鼠标及浏览器上的那个圈一直在转动,在IE678下,google的大牛们通过使用“htmlfile”解决了这个问题,IE9我试了,并不支持"htmlfile",当然IE9那个圈已经不转了。但是opera、chrome不支持“htmlfile”,无法解决。

    iframe的另一个问题就是请求的超时,我们需要判断当iframe超时时,对其刷新重新建立连接。在普通情况下,我们可以通过iframe的onload事件进行刷新,当iframe连接内容超时时就会触发onload事件。在“htmlfile”下iframe却不支持onload,但是能读取到iframe的readyState,当readyState为complete时即表示请求超时,所以我们可以通过setInterval来判断iframe的readyState进行刷新。

    至于php代码,本人不懂,无法做出解答。

    转载请注明出处:http://www.cnblogs.com/lecaf/

    如有任何建议或疑问,欢迎留言讨论。

    如果觉得文章不错的话,欢迎点一下右下角的推荐。

  • 相关阅读:
    html调用applet
    WindowListener中的windowClosed方法不执行的问题。
    有理数类 Java BigInteger实现
    有理数类 Java
    BigInteger构造函数解析
    求最大公约数(辗转相除法)
    Java 十六进制转十进制
    Java 十进制转十六进制
    ORA-12520: TNS:listener could not find available handler for requested type of server
    关于 error: Operation is not valid due to the current state of the object。
  • 原文地址:https://www.cnblogs.com/lecaf/p/2111618.html
Copyright © 2011-2022 走看看