Web通信之:长轮询(long-polling)

来源:互联网 发布:试客赚钱软件 编辑:程序博客网 时间:2024/04/30 00:38

原文链接:http://www.web-tinker.com/article/20046.html



“轮询”是个耐人寻味的词,第一次看到它的时候我就直接理解为“轮流查询”了。但是看到了英文才知道这个是网络通信专业的术语。轮询,其实就是一群人在排队买东西。polling这个词也生动的形容了这个的状态。就像这样

  轮询如果是排队买东西,那么长轮询就是排队上厕所。买东西的话,丢下钱就可以拿东西走了,但是上厕所就不一样,有些人说不定便秘半个小时都出不来。如果只用轮询去做Web通信,那服务器就鸭梨山大了,它需要一直做的接受和断开HTTP请求的操作。就像卖热销产品的店员就没有公共厕所管理员那么轻松。
  服务器就是厕所,需要上厕所的就是客户端的XHR对象。这就是长轮询的实现原理了。现在我做了一个例子,这个例子是当服务器上的某个文件被修改的时候就会把那个文件的内容输出到客户端,如果没有修改就一直保持“便秘”状态。我们先看服务器端的代码<?
//设置当前脚本为无超时状态
set_time_limit(0);
//操作的文件名
$DATAFILE='dat.txt';
//保存当前时间
$time=time();
//用死循环持续检测文件
while(1){
  //判断文件存在
  file_exists($DATAFILE) and
  //判断文件修改
  filemtime($DATAFILE)>$time and
  //输出文件内容并断开HTTP
  die(file_get_contents($DATAFILE));
  //清空文件状态缓存
  clearstatcache();
  //等待1秒
  sleep(1);
};
?>
  接着是客户端的代码,AJAX部分我就不注释了//检测浏览器
var isIE=navigator.userAgent.match(/MSIE (\d)/i);
isIE=isIE?isIE[1]:undefined;
//闭包
(function(){
  var xhr,f;
  //保存当前闭包指针
  f=arguments.callee;
  xhr=isIE<9
    ?new ActiveXObject("Microsoft.XMLHTTP")
    :new XMLHttpRequest;
  xhr.onreadystatechange=function(){
    if(xhr.readyState==4){
      //把接收到的文字输出
      var div=document.createElement("div");
      div.appendChild(
        document.createTextNode(xhr.responseText)
      );
      document.body.appendChild(div);
      f();//间接递归
    };
  };
  xhr.open("GET","test.php",true);
  xhr.send();
})();
  这样,当我们每次修改dat.txt并保存的时候,新的内容就会被输出到客户端。收到信息后客户端会再让一个XHR对象连接服务器等待dat.txt的下一次修改。

  以上就是长轮询的工作方式了。上面的例子只是说明了长轮询的工作原理,监视一个文件的改变只是一种操作方式而已。在你的程序中,可以监视数据库的变化或者做其他操作来判断是否要把数据输出到客户端。而且,数据并不局限于text/plain,你可以发送HTML、XML、JSON等所有你想要的格式让客户端程序自己去解析。
  比起轮询,长轮询可以节省很多HTTP连接和断开操作带来的开销。但是依然会消耗很多服务器资源