简易聊天室的实现 - Ajax轮询与长轮询
什么是轮询
轮询即rolling,通过Ajax循环访问服务端直到获取信息返回并关闭连接。
通俗点讲就是连续访问服务器,获取服务端数据并在前端输出。
Ajax轮询
对于Ajax轮询, 我们可以简单的一笔带过,因为他真的太消耗服务器资源了。
Ajax轮询前端 index.html
通过每隔一段时间访问后端 server.php
并通过Jquery更新页面信息,后端负责判断是否有新信息通过json的形式传递给前端,我们来看一个样例:
前端:
1 2 3 4 5 6 7 8 9 10 11 12
| <script> function getData() { $.ajax({ url: 'server.php', type: 'get', success: function (data) { console.log(data); } }) } setInterval("getData()",1000); </script>
|
后端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?php define('DATABASE','./database.json'); $f = new file(); echo json_decode($f->read(DATABASE),true);
class file {
function read($filepath) { if (file_exists($filepath)) { $str = file_get_contents($filepath); return json_decode($str,true); } else { self::write($filepath,''); } } } ?>
|
而这种Ajax轮询的方式无论如何都会每1s访问一次服务端,前一次请求完成后,无论有无结果返回,一秒之后下一次请求又会发出。这就叫做Ajax轮询。这边会导致严重消耗服务器资源,并且存在可能1s的延迟问题。(上述示例仅供方法参考,并不是最终样式)我们可以用伪代码来演示以下实现原理:
1 2 3 4 5 6 7
| <?php while(true) { file_get_contents('server.php'); sleep(1); } ?>
|
Ajax长轮询
对于聊天室的实现,相比Ajax轮询,Ajax长轮询是一个更好的方式。它优化了客户端与服务端之间的信息获取逻辑。通过前端设置一个较长的超时时间(如60秒),客户端访问一次后端,由后端判断是否存在新消息,如果有则 echo
出来,没有则将前端挂起(不会断开连接,知道有新消息或到达超时时间)这就完美的解决了消息延迟以及很大程度上缓解了服务器压力。下面我们看一个样例:
前端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function getData() { $.ajax({ method: 'GET', url: 'server.php', timeout: 50000, success: function(data) { console.log(data) getData(); }, error: function(res) { getData(); } }); } getData();
|
后端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?php define('DATABASE','./database.json'); $f = new file(); echo json_decode($f->read(DATABASE),true);
class file {
function read($filepath) { if (file_exists($filepath)) { $str = file_get_contents($filepath); return json_decode($str,true); } else { self::write($filepath,''); } } } ?>
|
我们可以用伪代码表示:
1 2 3 4 5 6 7 8 9 10
| <?php while(true) { if(无数据返回){ 等待数据返回(不断开连接) } else { 有数据返回,返回给前端; } } ?>
|
完整样例
对于Ajax长轮询我提供了一个完整的样例,包括前端后端,可以直接部署参照.
https://github.com/soxft/xchat