PHP使用反向Ajax技术实现在线客服系统详解


Posted in PHP onJuly 01, 2019

本文实例讲述了PHP使用反向Ajax技术实现在线客服系统。分享给大家供大家参考,具体如下:

反向Ajax技术,又称为服务器推技术,server push等。一般用于“在线客服”、“消息推送”、“即时通信”等功能中,比如新浪微博的私信功能,就是客户端不断的请求服务器并创建连接,去查看服务器有没有返回的信息,建立连接比较浪费服务器资源,下面我将根据客户端创建连接的不同性来介绍一下实现反向Ajax的三种思路。

三种思路:

1、间隔固定时间创建连接

这种方式就是按照固定时间不断的去请求服务器,当创建第一个连接时,不管是否有数据返回,此次连接都会失效,然后隔一段时间发出第二个请求,不断重复此动作,此法最浪费资源。

PHP使用反向Ajax技术实现在线客服系统详解

2、长连接方式

这种方式始终只创建一个连接,而这个连接不断开,被称为长时连接,以此不断获取服务器推送的数据,这种方式只创建一个连接,比第一种方法较好。

PHP使用反向Ajax技术实现在线客服系统详解

3、长连接+长轮询方式

这种方式始终创建连接,而这个连接也是长时连接,但是如果获得服务器推送的数据,此连接断开,然后隔固定时间创建第二此连接,这种方式最好,新浪微博的私信功能用的就是这种方法。

PHP使用反向Ajax技术实现在线客服系统详解

在线客服系统

实现思路:

(1)咨询用户端发出问题,把问题存入数据库,把咨询内容显示到客服人员的聊天窗口中
(2)客服人员看到聊天窗口后,选择咨询用户,进行回复,然后把回复内容显示到客服人员窗口中

实现方法:

此系统我采用上述思想中的第二种和第三种方式共同实现,咨询用户端采用第三种方式实现,客服人员端采用第二种方式实现。

数据库信息:

mid:主键,pos表示发送人,rec表示接收人,isread表示是否已读,content表示咨询/回复内容。

PHP使用反向Ajax技术实现在线客服系统详解

项目结构图:

PHP使用反向Ajax技术实现在线客服系统详解

客服人员界面(16-kefu-amdin.php):

此处采用长连接。页面中主要有一个div,用于显示聊天信息,还有一个隐藏的iframe标签,这个iframe实现反向Ajax模型,用于发送长时连接,当服务器有数据时,服务器将调用comet()方法,此方法显示咨询内容,choose()方法是选择咨询人,resp()是回复方法,在这里会向16-kefu-sendmsg.php页面发出ajax请求,向数据库插入一条回复信息,回复成功后并显示到聊天窗口中。

<?php
setcookie('username','admin');
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>客服功能——客服人员端</title>
  <link rel="stylesheet" href="">
<script>
  var xhr = new XMLHttpRequest();
  //服务器调用函数
  function comet(json){
    var content = '<p style="text-align:left"><span onclick="choose(\''+ json.pos +'\');">' + json.pos + '</span>说:'+json.content+'</p>';
    var old = document.getElementById('chatArea').innerHTML;
    document.getElementById('chatArea').innerHTML = old + content;
  }
  //咨询人选择函数
  function choose(pos){
    document.getElementById('postman').innerHTML = pos;
  }
  //客服人员回复函数
  function resp(){
    var respContent = document.getElementById('respContent').value;
    var pos = document.getElementById('postman').innerHTML;
    if(respContent == '' || pos == ''){
      alert('请重新选择回复人或填写回复内容');
      return;
    }
    //ajax提交请求
    xhr.open('POST','16-kefu-sendmsg.php',true);
    xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    xhr.onreadystatechange = function (){
      if(this.readyState == 4 && this.status == 200){
        if(this.responseText == 'ok'){
          //回复成功,把回复信息显示到聊天界面中
          var content = '<p style="text-align:right">你回复'+ pos + ':'+respContent+'</p>';
          var old = document.getElementById('chatArea').innerHTML;
          document.getElementById('chatArea').innerHTML = old + content;
          document.getElementById('respContent').value = '';//给回复内容重新置空
        }
      }
    }
    var sendData = 'rec=' + pos + '&content='+respContent;
    xhr.send(sendData);
  }  
</script>
<style>
  #chatArea{
    width:500px;
    height:400px;
    border:1px solid black;
    overflow: scroll;
  }
</style>
</head>
<body>
  <h1>客服功能——客服人员端</h1>
  <h2>原理:iframe+长连接</h2>
  <div id="chatArea">
  </div>
  <iframe width="0" height="0" frameborder="0" name="frame" src="./16-kefu-iframe.php"></iframe>
  <p>咨询人:<span id="postman"></span></p>
  <p><textarea id="respContent"></textarea></p>
  <p><input type="button" value="回复" onclick="resp();" /></p>
</body>
</html>

发送咨询/回复消息(16-kefu-sendmsg.php)

主要是接受信息,把数据写入到数据库中

<?php
/**
 * 客服回复咨询人,咨询人咨询客服
 * @author webbc
 */
header('Content-type:text/html;charset=utf-8');
require('./conn.php');
$rec = $_POST['rec'];//咨询人变为接收者
$pos = $_COOKIE['username'];//客服人员变为发送者
$respContent = $_POST['content'];//客服人员的回复内容
$sql = "insert into msg (pos,rec,content) values ('$pos','$rec','$respContent')";
echo mysql_query($sql) ? 'ok':'fail';
?>

客户人请求咨询信息(16-kefu-iframe.php)

主要功能是保持连接永不断开,然后不断的从数据库读取一条未读的咨询消息,如果有消息,先设置该消息为已读,返回js脚本,影响iframe的父窗体

<?php
/**
 * 通过iframe来实现反向Ajax
 * @author webbc
 */
header('Content-type:text/html;charset=utf-8');
set_time_limit(0);//设置页面永久执行
//ob_start();//打开输出缓存过了,就不需要使用此函数了
//由于浏览器是根据内容大小才先显示,可以先显示4000个空白字符串让浏览器可以继续显示
echo str_repeat(' ', 4000),"<br/>";
ob_flush();
flush();
while(true){
  //从数据库读取一条未读的咨询消息
  require('./conn.php');
  $sql = "select * from msg where rec = 'admin' and isread = 0 limit 0,1";
  $result = mysql_query($sql);
  $msg = mysql_fetch_assoc($result);
  //如果有消息
  if(!empty($msg)){
    //设置该消息为已读
    $sql = 'update msg set isread = 1 where mid = '.$msg['mid'];
    mysql_query($sql);
    $json = json_encode($msg);//把数组转换为json数据
    //返回js脚本,影响iframe的父窗体
    echo '<script>';
    echo 'parent.window.comet(',$json,');';
    echo '</script>';
    ob_flush();//强制让php返回给apache
    flush();//强制让web服务器返回给浏览器
  }
  sleep(1);//隔1s循环查1次
}
?>

咨询人员界面(16-kefu-user.php):

此处采用长连接+长轮询的方式。当页面加载就发出一条ajax请求,如果该请求有数据返回,则显示到聊天窗口中,延时1s后重新发送请求,如果点击咨询,就发出ajax请求将咨询内容写入数据库中。

<?php
  setcookie('username','user'.rand(10000,99999));
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>客服功能——客服人员端</title>
  <link rel="stylesheet" href="">
<script src="http://libs.baidu.com/jquery/1.7.2/jquery.min.js"></script>
<script>
//咨询方法
function ask(){
  var askContent = $('#askContent').val();
  if(askContent == ''){
    alert('请输入咨询内容');
    return ;
  }
  $.post('./16-kefu-sendmsg.php',{rec:'admin',content:askContent},function(res){
    if(res == 'ok'){
      $('<p style="text-align:right">你对客服说:'+askContent+'</p>').appendTo($('#chatArea'));
      $('#askContent').val('');
    }
  });
}
</script>
<style>
  #chatArea{
    width:500px;
    height:400px;
    border:1px solid black;
    overflow: scroll;
  }
</style>
</head>
<body>
  <h1>客服功能——用户端</h1>
  <h2>原理:ajax+长连接+长轮询</h2>
  <div id="chatArea">
  </div>
  <p><textarea id="askContent"></textarea></p>
  <p><input type="button" value="咨询" onclick="ask();" /></p>
</body>
<script>
  //长连接+长轮询
  var setting = {
    url:'16-kefu-ajax.php',
    dataType:'json',
    success:function(res){
      $('<p style="text-align:left">客服对你说:'+res.content+'</p>').appendTo($('#chatArea'));
      var func = function(){$.ajax(setting)};
      window.setTimeout(func,1000);//延时1s后重新发送连接
    }
  }
  $.ajax(setting);
</script>
</html>

咨询人请求回复信息界面(16-kefu-ajax.php):

通过ajax+长轮询实现反向Ajax。请求数据,获取数据后,将数据置为已读,然后返回,结束本次连接。

<?php
/**
 * 通过ajax+长轮询实现反向Ajax
 * @author webbc
 */
set_time_limit(0);//不设置请求超时时间
require('./conn.php');
$rec = $_COOKIE['username'];
$sql = "select * from msg where rec = '$rec' and isread = 0 limit 0,1";
while(true){
  $result = mysql_query($sql);
  $msg = mysql_fetch_assoc($result);
  //如果有客服人员的回复信息
  if(!empty($msg)){
    //把该信息置为已读
    $sql = "update msg set isread = 1 where mid = ".$msg['mid'];
    mysql_query($sql);
    echo json_encode($msg);//返回json数据
    exit();//如果此次连接获取数据,就结束本次连接
  }
  sleep(1);//隔一秒循环1次
}
?>

数据库连接文件(conn.php):

<?php
$conn = mysql_connect('localhost','root','1234');
mysql_query('use test;');
mysql_query('set names utf8');
?>

运行结果图:

PHP使用反向Ajax技术实现在线客服系统详解

更多关于PHP相关内容可查看本站专题:《PHP+ajax技巧与应用小结》、《PHP网络编程技巧总结》、《PHP基本语法入门教程》、《php面向对象程序设计入门教程》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
Access数据库导入Mysql的方法之一
Oct 09 PHP
PHP 日期时间函数的高级应用技巧
Oct 10 PHP
解析php中两种缩放图片的函数,为图片添加水印
Jun 14 PHP
php接口和抽象类使用示例详解
Mar 02 PHP
php操作xml入门之xml标签的属性分析
Jan 23 PHP
CentOS下PHP安装Oracle扩展
Feb 15 PHP
php采用session实现防止页面重复刷新
Dec 24 PHP
php 反斜杠处理函数addslashes()和stripslashes()实例详解
Dec 25 PHP
实例分析基于PHP微信网页获取用户信息
Nov 24 PHP
PHP+MySQL高并发加锁事务处理问题解决方法
Apr 30 PHP
Thinkphp5框架实现获取数据库数据到视图的方法
Aug 14 PHP
关于PHP5.6+版本“No input file specified”问题的解决
Dec 11 PHP
PHP封装cURL工具类与应用示例
Jul 01 #PHP
PHP session垃圾回收机制实例分析
Jun 28 #PHP
PHP常用的类封装小结【4个工具类】
Jun 28 #PHP
php实现网页上一页下一页翻页过程详解
Jun 28 #PHP
php输出控制函数和输出函数生成静态页面
Jun 27 #PHP
php生成静态页面并实现预览功能
Jun 27 #PHP
PHP创建对象的六种方式实例总结
Jun 27 #PHP
You might like
PHP Session变量不能传送到下一页的解决方法
2009/11/27 PHP
PHP原生模板引擎 最简单的模板引擎
2012/04/25 PHP
PHP实现提取一个图像文件并在浏览器上显示的代码
2012/10/06 PHP
PHP实现邮件群发的源码
2013/06/18 PHP
如何使用PHP对网站验证码进行破解
2015/09/17 PHP
php使用curl代理实现抓取数据的方法
2017/02/03 PHP
PHP7创建销毁session的实例方法
2020/02/03 PHP
PHPstorm启用自动换行的方法详解(IDE)
2020/09/17 PHP
利用javascript/jquery对上传文件格式过滤的方法
2009/07/25 Javascript
kmock javascript 单元测试代码
2011/02/06 Javascript
javascript中数组的concat()方法使用介绍
2013/12/18 Javascript
JavaScript编程学习技巧汇总
2016/02/21 Javascript
js拼接html字符串的注意事项
2016/10/13 Javascript
微信小程序 Page()函数详解
2016/10/17 Javascript
Angular 4依赖注入学习教程之Injectable装饰器(六)
2017/06/04 Javascript
mpvue将vue项目转换为小程序
2018/09/30 Javascript
在NodeJs中使用node-schedule增加定时器任务的方法
2020/06/08 NodeJs
在vue中封装方法以及多处引用该方法详解
2020/08/14 Javascript
解决vant中 tab栏遇到的坑 van-tabs
2020/11/04 Javascript
windows下Virtualenvwrapper安装教程
2017/12/13 Python
使用 Python 玩转 GitHub 的贡献板(推荐)
2019/04/04 Python
Python3.7黑帽编程之病毒篇(基础篇)
2020/02/04 Python
HTML5有哪些新特征
2015/12/01 HTML / CSS
Html5监听手机摇一摇事件的实现
2019/11/07 HTML / CSS
香港No.1得奖零食网:香港零食大王
2016/07/22 全球购物
秘鲁购物网站:Linio秘鲁
2017/04/07 全球购物
瑜伽灵感珠宝:Satya Jewelry
2018/01/06 全球购物
Molly Bracken法国电子商店:法国女性时尚品牌
2019/07/24 全球购物
NICKIS.com荷兰:设计师儿童时装
2020/01/08 全球购物
Diesel美国网上商店:意大利牛仔时装品牌
2020/12/10 全球购物
艺术设计专业毕业生推荐信
2014/07/08 职场文书
学习党的群众路线实践活动思想汇报
2014/09/12 职场文书
领导欢迎词范文
2015/01/26 职场文书
2019年让高校“心动”的自荐信
2019/03/25 职场文书
《悬崖边的树》读后感2篇
2019/12/02 职场文书
OpenCV中resize函数插值算法的实现过程(五种)
2021/06/05 Python