天天看點

實作一個簡單的服務端推送方案-執行個體篇Push

這篇講Push,即浏覽器用戶端被動等待無須輪循,伺服器連不間斷的向前端推送伺服器目前時間。

用戶端代碼,JS庫為prototype.js:

<!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" src="prototype.js"></script>
  </head>
  <body>
    <div id="content">The server time will be shown here</div>

<script type="text/javascript">
var comet = {
  connection   : false,
  iframediv    : false,
  initialize: function() {
    if (navigator.appVersion.indexOf("MSIE") != -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.body.appendChild(comet.iframediv);
      comet.connection.parentWindow.comet = comet;
      comet.iframediv.innerHTML = "<iframe id='comet_iframe' src='./backend.php'></iframe>";      
    } else if (navigator.appVersion.indexOf("KHTML") != -1) {
      // for KHTML browsers
      comet.connection = document.createElement('iframe');
      comet.connection.setAttribute('id',     'comet_iframe');
      comet.connection.setAttribute('src',    './backend.php');
      with (comet.connection.style) {
        position   = "absolute";
        left       = top   = "-100px";
        height     = width = "1px";
        visibility = "hidden";
      }
      document.body.appendChild(comet.connection);
    } else {   
      // For other browser (Firefox...)
      comet.connection = document.createElement('iframe');
      comet.connection.setAttribute('id',     'comet_iframe');
      with (comet.connection.style) {
        left       = top   = "-100px";
        height     = width = "1px";
        visibility = "hidden";
        display    = 'none';
      }
      comet.iframediv = document.createElement('iframe');
      comet.iframediv.setAttribute('src', './backend.php');
      comet.connection.appendChild(comet.iframediv);
      document.body.appendChild(comet.connection);
    }
  },
  // this function will be called from backend.php  
  printServerTime: function (time) {
    $('content').innerHTML = time;
  },
  onUnload: function() {
    if (comet.connection) {
      comet.connection = false; // release the iframe to prevent problems with IE when reloading the page
    }
  }
}
Event.observe(window, "load",   comet.initialize);
Event.observe(window, "unload", comet.onUnload);
</script>

</body>
</html>
           

伺服器PHP代碼,backend.php:

<?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
  echo '<script type="text/javascript">';
  echo 'comet.printServerTime('.time().');';
  echo '</script>';
  print str_pad("",10000);  //在輸出前必須輸出足夠的字元才會顯示到浏覽器
  flush(); // used to send the echoed data to the client
while(1) {
  $ywparam = time();
  error_log(date("[Y-m-d H:i:s]")." > ".$ywparam."\n", 3 , "/usr/local/apache2219/logs/php_log");
  echo '<script type="text/javascript">';
  echo 'comet.printServerTime('.time().');';
  echo '</script>';
  //print str_pad("",10000);  //在輸出前必須輸出足夠的字元才會顯示到浏覽器
  ob_flush();  //或者向上一條語句寫夠4096個位元組以上
  flush(); // used to send the echoed data to the client
  sleep(1); // a little break to unload the server CPU
}
?>
</body>
</html>