zoukankan      html  css  js  c++  java
  • Js和Jquery实现ajax长轮询

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

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

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

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

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

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

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

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

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

    长轮询的服务器端实现:

    聊天信息存储:

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

    CREATE TABLE `msg` (
      `msgid` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `sender` char(16) NOT NULL,
      `receiver` char(16) NOT NULL,
      `content` text,
      `senderRead` tinyint(1) DEFAULT '0',
      `receiverRead` tinyint(1) DEFAULT '0',
      PRIMARY KEY (`msgid`)
    ) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
    

    PHP脚本:

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

    <?php 
    
    set_time_limit(0);//设置脚本超时时间为无限,不然在过了超时时间后脚本会自动关闭,轮询失败。
    
    $link=new mysqli("127.0.0.1","root","root","test");
    
    $search="select sender,receiver,content from msg where receiverRead=0 limit 1";//限制每次读出一条数据,便于修改其已读flag
    
    $change="update msg set receiverRead=1 where receiverRead=0 limit 1";
    
    while (true) {//进入无限循环
    
    	$res = null;
    
    	$res=$link->query($search);
    
    	if($res->num_rows!=0){
    
    		$link->query($change);
    
    		$msg=$res->fetch_assoc();
    
    		$jsonstr=json_encode($msg);
    
    		echo $jsonstr;
    
    		break;
    	}
    	usleep(1000);//如果没有信息不会进入if块,但会执行一下等待1秒,防止PHP因循环假死。
    }
    
    ?>
    

    客户端实现:

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

    用原生JS:

    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8">
    	<title>	</title>
    </head>
    <body>
    
    </body>
    <script>
    	function link(){
    
    	    var xhr=null;//先设置xhr为空,为了轮询时再次调用函数对xhr重用,引发错误
    
    	    xhr=new XMLHttpRequest();
    
    	    xhr.open('GET','server.php',true);//第三个参数一定要设置为true,异步不阻塞,不会影响到后面JS的执行。
    
    	    xhr.send();
    
    	    xhr.onreadystatechange=function(){
    
    	    	if(xhr.readyState==4 && xhr.status==200){
    
    	    		var obj = JSON.parse(xhr.responseText)
    
    	    		console.log('发送人:'+obj.sender+'接收人:'+obj.receiver+'内容:'+obj.content)
    
    	    		setTimeout(function(){link()},3000)
    	    	}
    	    };
    	}
    	link();
    </script>
    </html>
    
  • 相关阅读:
    Python——Sublime Text3编写Python的一些问题
    html/css/js----js中遇到的一些问题
    eclipse--常见问题
    前端如何实现拖拽效果(一)
    在vue中如何实现上传本地视频和图片预览
    关于NodeJS中mysql连接池卡死问题
    学习Mysql3——约束条件
    Vuex基础用法
    学习Mysql2--增删改查
    学习Mysql1——mysql安装和基本命令使用
  • 原文地址:https://www.cnblogs.com/jinxiblog/p/10546775.html
Copyright © 2011-2022 走看看