javascript和jQuery实现网页实时聊天的ajax长轮询_javascript技巧

介绍

大家都知道,HTTP协议是一个属于应用层的面向对象的协议,HTTP 协议一共有五大特点:

1、支持客户/服务器模式;

2、简单快速;

3、灵活;

4、无连接;

5、无状态。

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

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

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 int not null primary key auto_increment,

  sender char(16) not null,

  receiver char(16) not null,

  content text, //信息内容用text类型,存储量可达到65535字符

  senderRead tinyint enum(0,1) default 0,

  receiverRead tinyint enum(0,1) default 0 //设置一个是否已读的flag标记

}

PHP脚本:

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

set_time_limit(0);//设置脚本超时时间为无限,不然在过了超时时间后脚本会自动关闭,轮询失败。
 $link=new mysqli("host","user","password","database");
 $search="select sender,receiver,content from msg where receiverRead=0 limit 1";//限制每次读出一条数据,便于修改其已读flag
 $change="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插件实现:

var link={           //jQuery的AJAX执行的配置对象
  type:"GET",      //设置请求方式,默认为GET,
  async:true,      //设置是否异步,默认为异步
  url:"customback.php",
  dataType:"json",    //设置期望的返回格式,因服务器返回json格式,这里将数据作为json格式对待
  success:function (msg){
      process...
     setTimeout("link()",300);
  }              //成功时的回调函数,处理返回数据,并且延时建立新的请求连接
}
$.ajax(link);          //执行ajax请求。

]

程序扩充:

添加发送聊天窗口:

新建一个函数用来处理ajax的POST请求,用ajax将发信人,每次发送的信息,收信人发送到服务器端,并设置一个单独的PHP脚本处理信息,将信息插入数据库。

需要注意的是,用JS原生实现POST请求发送信息时,要设置ajax对象的HTTP头,模拟表单提交的操作:

xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");

聊天室消息处理:

为了防止每次都查询到全部信息,我们对数据库的查询操作更改一下,设置idflag=0,每次查询后,设置idflag为查询到的数据的id,查询时我们查询比idflag大的ID,即,新添加进去的信息。

好了,本文到此就结束了,利用本文的示例代码一个简单的聊天室程序就做好了,感兴趣的可以快快实践下了。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索jquery
, ajax
, 聊天室
, 长轮询
ajax实现实时聊天
jquery ajax轮询、jquery ajax 长轮询、jquery ajax实时刷新、jquery ajax 实时搜索、jquery ajax实时更新,以便于您获取更多的相关知识。

时间: 2024-08-24 23:59:11

javascript和jQuery实现网页实时聊天的ajax长轮询_javascript技巧的相关文章

深入探讨JavaScript、JQuery屏蔽网页鼠标右键菜单及禁止选择复制_javascript技巧

我记得在刚开始接触动态HTML及JavaScript时就接触过关于鼠标右键屏蔽的脚本代码,当时这些代码很多会用在防止浏览者未经允许的复制网页上的文字或者其他内容,后来的实际应用证明这种做法是不符合用户体验的,而且破解的方法也有很多,比如我曾经写过一篇文章讲解如何解除网页禁止复制的办法. 由此可见,限制右键及复制是不明智的做法,但是今天我仍然要谈谈关于禁止网页复制.右键菜单的事儿,因为随着网页APP技术的发展,网页应用和桌面应用之间的界限越来越模糊,有一些桌面程序实际上是由网页配合JavaScri

jquery与php结合实现AJAX长轮询(LongPoll)_AJAX相关

HTTP是无状态.单向的协议,用户只能够通过客服端向服务器发送请求并由服务器处理发回一个响应.若要实现聊天室.WEBQQ.在线客服.邮箱等这些即时通讯的应用,就要用到" 服务器推送技术(Comet)". 传统的AJAX轮询方式,客服端以用户定义的时间间隔去服务器上查询最新的数据.种这种拉取数据的方式需要很短的时间间隔才能保证数据的精确度,但太短的时间间隔客服端会对服务器在短时间内发送出多个请求. 反转AJAX,就是所谓的长轮询或者COMET.服务器与客服端需要保持一条长时间的请求,它使

jquery与php结合实现AJAX长轮询(LongPoll)

HTTP是无状态.单向的协议,用户只能够通过客服端向服务器发送请求并由服务器处理发回一个响应.若要实现聊天室.WEBQQ.在线客服.邮箱等这些即时通讯的应用,就要用到" 服务器推送技术(Comet)". 传统的AJAX轮询方式,客服端以用户定义的时间间隔去服务器上查询最新的数据.种这种拉取数据的方式需要很短的时间间隔才能保证数据的精确度,但太短的时间间隔客服端会对服务器在短时间内发送出多个请求. 反转AJAX,就是所谓的长轮询或者COMET.服务器与客服端需要保持一条长时间的请求,它使

jquery在Chrome下获取图片的长宽问题解决_javascript技巧

遇到个需要获得图片的长宽的问题.在IE.FireFox下均正常,就TMD在Chrome中不行,网上非有人说可以,然后还归结为是不是Chrome版本问题. 终于的终于,找到了答案. 在大多数情况下,把js代码放到图片标签的后面: 复制代码 代码如下: <img id="test" src="**.jpg" /> <script> alert(document.getElementById("test").width;<

《Web异步与实时交互——iframe AJAX WebSocket开发实战》—— 1.3 Web实时交互方式——轮询、长轮询、长连接及推送

1.3 Web实时交互方式--轮询.长轮询.长连接及推送 如何实时获取服务器端的最新数据,是Web实时交互关注的内容.在介绍Web实时交互方式前,先来具体了解HTTP的通信机制,为之后概念的精准定义做铺垫.HTTP通信过程可分为4步. 第1步:HTTP是基于传输层的TCP协议,在HTTP工作开始之前,Web浏览器首先要通过网络与Web服务器在TCP层建立连接.在TCP层进行"三次握手"之后,建立了TCP连接,此时HTTP就可以进行传输了(注意,由于HTTP为无连接.无状态的协议,在本书

PHP/Javascript/CSS/jQuery常用知识大全详细整理第1/2页_php技巧

1. 变量如何定义?如何检查变量是否定义?如何删除一个变量?怎样检测变量是否设置?       $定义   isset()// 检测变量是否设置        defined()// 检测常量是否设置       unset()//销毁指定的变量       empty()// 检测变量是否为空 2. 什么是可变变量?       一个变量的变量名可以动态的设置和使用.       $a = 'hello' , $$a = 'world',  ${$a}=hello world3. 变量赋值方式

JavaScript控制网页层收起和展开效果的方法_javascript技巧

本文实例讲述了JavaScript控制网页层收起和展开效果的方法.分享给大家供大家参考.具体如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <meta http-equiv="pragma" content=&q

详解原生JavaScript实现jQuery中AJAX处理的方法_javascript技巧

在这篇文章,我使用 Node.js作为后端.没错,这就可以全栈(浏览器和服务器)JS了.Node.js 是很简洁的,我鼓励你能在 Github下载demo,并关注该项目.下面是服务器端的代码: // app.js var app = http.createServer(function(req, res){ if(req.url.indexOf("/scripts/") >= 0){ render(req.url.slice(1), "application/javas

Jquery调用iframe父页面中的元素及方法_javascript技巧

一.在iframe中查找父页面元素的方法: $('#id', window.parent.document) 二.在iframe中调用父页面中定义的方法和变量: parent.method parent.value 三.实例 父页面: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="IframeDemo._De