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 相关文章推荐
php 获取完整url地址
Dec 20 PHP
兼容性最强的PHP生成缩略图的函数代码(修改版)
Jan 18 PHP
php查看请求头信息获取远程图片大小的方法分享
Dec 25 PHP
PHP中执行MYSQL事务解决数据写入不完整等情况
Jan 07 PHP
php快递单号查询接口使用示例
May 05 PHP
PHP循环输出指定目录下的所有文件和文件夹路径例子(简单实用)
May 10 PHP
模板引擎smarty工作原理以及使用示例
May 25 PHP
CentOS安装php v8js教程
Feb 26 PHP
smarty模板引擎之内建函数用法
Mar 30 PHP
PHP如何将XML转成数组
Apr 04 PHP
PHP中CheckBox多选框上传失败的代码写法
Feb 13 PHP
Laravel框架下的Contracts契约详解
Mar 17 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实现采集程序原理和简单示例代码
2007/03/18 PHP
php木马攻击防御之道
2008/03/24 PHP
php文件上传的例子及参数详解
2013/12/12 PHP
PHP上传图片进行等比缩放可增加水印功能
2014/01/13 PHP
使用PHP强制下载PDF文件示例
2014/01/17 PHP
php根据isbn书号查询amazon网站上的图书信息的示例
2014/02/13 PHP
一个简单的php MVC留言本实例代码(必看篇)
2016/09/22 PHP
php使用filter_var函数判断邮箱,url,ip格式示例
2019/07/06 PHP
form中限制文本字节数js代码
2007/06/10 Javascript
js修改input的type属性及浏览器兼容问题探讨与解决
2013/01/23 Javascript
Jquery显示、隐藏元素以及添加删除样式
2013/08/09 Javascript
JQuery中阻止事件冒泡几种方式及其区别介绍
2014/01/15 Javascript
JS实现当前页居中分页效果的方法
2015/06/18 Javascript
如何通过js实现图片预览功能【附实例代码】
2016/03/30 Javascript
浅析JS异步加载进度条
2016/05/05 Javascript
微信小程序 支付功能(前端)的实现
2017/05/24 Javascript
jQuery封装placeholder效果实现方法,让低版本浏览器支持该效果
2017/07/08 jQuery
vue单页应用加百度统计代码(亲测有效)
2018/01/31 Javascript
解决修复npm安装全局模块权限的问题
2018/05/17 Javascript
使用apifm-wxapi快速开发小程序过程详解
2019/08/05 Javascript
jQuery单页面文字搜索插件jquery.fullsearch.js的使用方法
2020/02/04 jQuery
解决vue axios跨域 Request Method: OPTIONS问题(预检请求)
2020/08/14 Javascript
python3获取文件中url内容并下载代码实例
2019/12/27 Python
Python pip配置国内源的方法
2020/02/14 Python
Python多进程编程multiprocessing代码实例
2020/03/12 Python
python实现测试工具(二)——简单的ui测试工具
2020/10/19 Python
Python Spyder 调出缩进对齐线的操作
2021/02/26 Python
HTML5不支持frameset的两种解决方法
2016/11/14 HTML / CSS
英国领先的鞋类零售商:Shoe Zone
2018/12/13 全球购物
我爱我的祖国演讲稿
2014/05/04 职场文书
贫困证明模板(3篇)
2014/09/16 职场文书
2015年收银员个人工作总结
2015/04/01 职场文书
《扇形统计图》教学反思
2016/02/17 职场文书
2019年房屋委托租赁合同范本(通用版)!
2019/07/17 职场文书
win10下go mod配置方式
2021/04/25 Golang
mysql 8.0.27 绿色解压版安装教程及配置方法
2022/04/20 MySQL