即时消息原理:
当客户端发起长连接请求(轮询),服务器端监听到发现数据更新了,立即向客户端推送消息给客户端,客户监听到响应后即渲染处理展示。
以下根据原理得出的基本方案:
方案一:在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>)。