HTML5技术

网页实时聊天之js和jQuery实现ajax长轮询 - 枕边书

字号+ 作者:H5之家 来源:博客园 2015-11-14 17:14 我要评论( )

众所周知,HTTP协议是无状态的,所以一次的请求都是一个单独的事件,和前后都没有联系。所以我们在解决网页实时聊天时就遇到一个问题,如何保证与服务器的长时间联系,从而源源不段地获取信息。 一直以来的方式无非有这么几种: 1、长连接,即服务器端不断开

众所周知,HTTP协议是无状态的,所以一次的请求都是一个单独的事件,和前后都没有联系。所以我们在解决网页实时聊天时就遇到一个问题,如何保证与服务器的长时间联系,从而源源不段地获取信息。

一直以来的方式无非有这么几种:

1、长连接,即服务器端不断开联系,PHP服务器端用ob系列函数来不停的读取输出,但是相当耗费服务器资源。

2、Flash socket,flash的as3语言,创建一个socket服务器用来处理信息。

3、轮询,顾名思义就是不停地发送查询消息,一有新消息立刻更新,但是会有多次无用请求。

4、长轮询,是轮询的升级版,需要服务器端的配合。

5、websocket,HTML5的通信功能,建立一个与服务器端的专用接口ws协议来进行通讯,兼容可能成为问题,改天研究一下这个。

这篇博文总结一下用JS和JQ两种方式(其实不同就是js和jq的实现),实现AJAX长轮询。

 

长轮询的思想:

如图:用AJAX发送询问信息,服务器在没有信息要返回的时候进入无限等待。由于AJAX异步的特性,PHP在服务器端执行等待不会影响到页面的正常处理。一旦服务器查询到返回信息,服务器返回信息,AJAX用回调函数处理这条信息,同时迅速再次发送一个请求等待服务器处理。

与传统轮询相比,长轮询在服务器没的返回信息的时候进入等待,减少了普通轮询服务器无数次的空回复。可以这样认为,长轮询使服务器每次的返回更有目的性,而不是盲目返回。

 

长轮询的服务器端实现:

聊天信息存储:

数据库设计为信息ID(msgid),发送人(sender),接收人(receiver),信息内容(content),设置senderRead和receiverRead的目的是标记信息是否已被读取,读取后改变标记,以区别信息是否已经被读取。

create table msg{   msgid auto_increment,   sender char(16) not null,   receiver char(16) not null,   content text, //信息内容用text类型,存储量可达到65535字符   senderRead tinyint enum(0,1) default 0,   receiverRead 设置一个是否已读的flag标记 }

PHP脚本:

 脚本的主要目的是处理来自ajax的每次询问,ajax每次询问就查询一下数据库,看有没有新的信息,如果没有,刚用usleep()函数等待一秒后再次查询,直到有新信息插入数据库并被查到,脚本返回查询到的数据,并退出无限循环,结束脚本。

=new mysqli("host","user","password","database"); ="update chat set receiverRead=1 where receiverRead=0 limit 1"; while (true) { //进入无限循环     $res=$link->query($sql); //查询结果    if($res->num_rows!=0){ //当有未读信息时读取信息       $link->query($change);//将信息的已读flag设为1       $msg=$res->fetch_assoc();       $jsonstr=json_encode($msg);//取到信息,将信息用转码为json格式,返回给JS       echo $jsonstr;       break;//输出信息后退出while循环,结束当前脚本     }   usleep(1000);//如果没有信息不会进入if块,但会执行一下等待1秒,防止PHP因循环假死。 }

 

客户端实现:

客户端的主要任务是设置一个ajax请求函数,每次查询时被调用,当没有信息返回时,服务器端被搁置,当前页面正常执行;当有信息返回时,函数处理返回的数据,并迅速再次调用此函数发送一次请求。

用原生JS:

function link(){ var xhr=null;//先设置xhr为空,为了轮询时再次调用函数对xhr重用,引发错误 xhr=new XMLHttpRequest(); xhr.open('GET','serviceback.php',true);//第三个参数一定要设置为true,异步不阻塞,不会影响到后面JS的执行。 xhr.send(); xhr.onreadystatechange=function(){     if (xhr.readyState==4) { 严密也可加使用(xhr.readyState==4 && xhr.status ==200)限定服务器响应码为200时才进行处理。       if(xhr.responseText!=''){         process... //服务器端返回信息,且返回信息不为空,则开始处理返回信息。       }   setTimeout("link()",300);

//递归再次调用link()函数,用setTimeOut()设置延时是因为服务器端进行sql操作时会耗时,当有新信息时,在服务器将要置已读flag为1还未成功时,AJAX可能已经又发出多条查询信息了,会导致一条信息多次返回。   } }; }

用jQuery插件实现:

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 网页适应所有屏幕宽度 - 侧耳倾听一场梦

    网页适应所有屏幕宽度 - 侧耳倾听一场梦

    2017-04-22 10:00

  • 网页版扫雷游戏 - 季末的寂寞

    网页版扫雷游戏 - 季末的寂寞

    2017-04-21 13:00

  • 基于CSS的个人网页 - 汕大-吴广林

    基于CSS的个人网页 - 汕大-吴广林

    2017-04-21 12:00

  • 调取百度地图接口,实现取自己的实时位置,然后可以在百度地图上添加信息标注 - QISHUANG

    调取百度地图接口,实现取自己的实时位置,然后可以在百度地图上添加

    2017-04-18 10:02

网友点评
t