即时消息原理:

 

当客户端发起长连接请求(轮询),服务器端监听到发现数据更新了,立即向客户端推送消息给客户端,客户监听到响应后即渲染处理展示。

 

以下根据原理得出的基本方案:

 

方案一:在HTML文件中加入 <META HTTP-RQUIV="Refresh" CONTENT=12>,实现刷新。这将自动指示浏览器在指定秒数之后重新装载页面。

优点 :不需要服务器端的配置。

缺点 :

a) 糟糕的用户体验

b) 对服务器的压力很大,并且造成带宽的极大浪费。

 

方案一:ajax轮询或者Linux的crontab定时向服务器询问有没有新消息

 

这个方案实现方法很简单,ajax轮询使用setTimeout即可实现,Linux的定时任务crontab,将需要的效果,写成脚本后配置服务器的即可,不多说。

 

优点:

a) 不需要太多服务器端的配置。

b) 降低带宽的负荷(因为服务器返回的不是完整页面)。

缺点:

a) 对服务器的压力并不会有明显的减少。

b) 实时性差,有一定的延迟。

 

方案三:ajax 与 comet实现长连接

 

好玩的终于来了,Comet方式通俗的说就是一种长连接机制(long lived http)。由浏览器端主动发起请求,服务器端发现数据更新后立即响应返回浏览器,它只需要连接一次,即可保持持久连接。当然comet也是会给服务器增加一定的负载,因为它一直占着连接。但也比第二种方案的性能好多。

简单案例:

 

<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<title>Comet Test</title>
<script type="text/javascript" src="http://lib.sinaapp.com/js/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
(function($){
   function handleResponse(response){
   $('#content').append('<div>' + response['msg'] + '</div>');
   }
 
   var timestamp = 0;
   var url = 'b.php';
   var noerror = true;
   var ajax;
 
   function connect() {
      ajax = $.ajax(url, {
         type: 'get',
         data: { 'timestamp' : timestamp },
         success: function(transport) {
            console.log(transport);
            eval('var response = '+transport);
            timestamp = response['timestamp'];
            handleResponse(response);
            noerror = true;
         },
         complete: function(transport) {
            (!noerror) && setTimeout(function(){ connect() }, 5000) || connect();

//此处是轮询的关键,之后会发现其实这样的效果也不是很理想,因为每次http请求断开之后,就会启用setTimeout连接回来。优化方案见推送技术学习(二)
            noerror = false;
         }
      });
   }
 
   function doRequest(request) {
      $.ajax(url, {
         type: 'get',
         data: { 'msg' : request }
      });
   }
 
   $('#cometForm').live('submit', function(){
      doRequest($('#word').val());
      $('#word').val('');
      return false;
   });
 
   $(document).ready(function(){
      connect();
   });
})(jQuery);
</script>
<div id="content"></div>
<div style="margin: 5px 0;">
<form action="javascript:void(0);" id="cometForm" method="get">
<input id="word" name="word" type="text" value="">
<input name="submit" type="submit" value="Send">
 
</form></div>

  

 

 

 服务器端处理:

<?php
 
$filename  = dirname(__FILE__).'/data.txt';
 
// 消息都储存在这个文件中
$msg = isset($_GET['msg']) ? $_GET['msg'] : '';
 
if ($msg != ''){
   file_put_contents($filename,$msg);
   die();
}
 
// 不停的循环,直到储存消息的文件被修改 ,用数据库也类似这样

$lastmodif    = isset($_GET['timestamp']) ? $_GET['timestamp'] : 0;
$currentmodif = filemtime($filename);

$response = array();
while ($currentmodif <= $lastmodif){ // 如果数据文件已经被修改
   $currentmodif = filemtime($filename);

// 返回json数组

$response['msg']       = file_get_contents($filename);
$response['timestamp'] = $currentmodif;
echo json_encode($response);

Ob_flush();
flush();//这里是comet推送技术核心,必须让请求的内容马上推送出去,不等待页面加载完成,即将内容从缓存中冲刷出来 
usleep(100000); // 100ms暂停 缓解CPU压力

}
 
?>

关于推送消息本人也在学习研究中,有更好的想法可以留言互相交流(gan<1976741895@qq.com>)。

posted on 2016-05-22 22:20  理货宝  阅读(262)  评论(1编辑  收藏  举报