PHP-Swoole+tp3+websocket+redis,利用接口制作客服实时对话聊天服务器

马星阑
2023-12-01

菜鸟一个,接受评价
直奔主题
1.在php中引入swoole扩展
2.利用swoole搭建websocket聊天服务器
tp3根目录创建server目录,用来存放搭建服务器的php文件,命名server.php(根据自己命名)

服务端:

<?php

/*
  在这里创建了一个chat类
*/

Class Chat{
   //监控所有IP
    const host='0.0.0.0';
    //端口设置
    const port = 8812;
    private $server = null;
    private $redis = null;

    public function __construct(){
  //创建websocket服务器
        $this->server = new swoole_websocket_server(self::host, self::port);
      //启动redis,用reids设置内置容器,装入在线人数
       $this->redis = new Redis();
        $this->redis->connect('127.0.0.1',6379); 

        $this->server->on('open',[$this,'onOpen']);

        $this->server->on('message',[$this,'onMessage']);

        $this->server->on('close',[$this,'onClose']);

        $this->server->start();


    }

    public function onopen($server,$request){


    }

    public function onMessage($server,$frame){

        /*
         * 判断此用户是否已在线
         * type 1/用户名 2/简单聊天
         */

       $data = json_decode($frame->data,true);
       

       if($data['type']==1){    
          $this->redis->hset('fdInfo',$data['user'],$frame->fd);
       }elseif($data['type']==2){
       /*
        * 检测对方是否在线
        */
         $customer_id = $this->redis->Hget('fdInfo',$data['customer']);
       foreach($server->connections as $fd){
        $arr_fd[] = $fd;
       }
       //检测所有在线人数Fd是否有你需要对话的人在线
       if(in_array($customer_id,$arr_fd)){
           $server->push($customer_id,$data['msg']);
       }
       /*
        * 离线或在线都导入进数据库
        * 在这里使用域名是因为,内置聊天服务器在后台运行,程序并不能用PHP函数进行自动获取网址
        */
              //新消息Api
       $chat_api = 'http://域名/Chatapi/insertchat?key=ZCNZNB&send_user='.$data['send_user'].'&msg='.$data['msg'].'&customer='.$data['customer'];
       //新聊天用户Api
       $news_api = 'http://域名/Chatapi/insertnews?key=ZCNZNB&send_user='.$data['send_user'].'&msg='.$data['msg'];
           file($chat_api);
          file($news_api);
       }
    }

    public function onClose($server,$fd){
    }
}
$obj = new Chat();

客户端-前端程序-用户端

//websocket

//在这里,如果不能成功连接到websocket服务器,就把127.0.0.1改为自己的Ip地址即可
   var url = 'ws://127.0.0.1:8812';
   
   socket=new WebSocket(url);
   //这里的user,是用户专属名字,是从后端传入的,一定要设置每个用户独立的名字
   var user =<?php echo $user; ?>

     socket.onopen=function(){
         console.log(user+'连接成功');
        var json = JSON.stringify({'type':1,'user':user});  
        socket.send(json);
        }
        
      socket.onmessage=function(data){
      console.log(data.data);
      }
        
     socket.onclose=function(){
         console.log(user+'断开连接');
     }
   


    function send(){
    var content = $('#content').val()
    /*设置后端名字为admin,专属用户接受信息,这样所有用户就只能与admin用户聊天,达到联系客服的效果
      customer 传输对象,与哪个用户聊天,就写哪个customer,因为需求为用户与后台聊天,则填写后台管理员
      admin
    */
  var json = JSON.stringify({'type':2,'send_user':user,'msg':content,'customer':'admin'});  
        socket.send(json);
    }
}

**

服务端-管理员

//websocket
//在这里,如果不能成功连接到websocket服务器,就把127.0.0.1改为自己的Ip地址即可
   var url = 'ws://127.0.0.1:8812';
   
   socket=new WebSocket(url);
   
   var user = admin;
   /*
   在这里,我是用get获取到用户名的,从而与不同的客户进行聊天,你们也可以用其他办法进行传值
   只要保证customer里是你想与这个用户聊天的用户名即可,因为要到后端进行针对发送信息
   */
  var customer =<?php echo $_GET['username']; ?>
  

   
     socket.onopen=function(){
         console.log(user+'连接成功');
        var json = JSON.stringify({'type':1,'user':user});  
        socket.send(json);
        }
        
      socket.onmessage=function(data){
      console.log(data.data);     
      }
        
     socket.onclose=function(){
         console.log(user+'断开连接');
     }
   


    function send(){
    var content = $('#content').val()
        //发送消息到服务器
        var json = JSON.stringify({'type':2,'send_user':user,'msg':content,'customer':customer});  
        socket.send(json);
    }
}

聊天服务器-保存聊天信息接口

在这里,你要根据tp3的路由进行写接口,我这边是用get接口,你也可以自己写个内置curl类,进行post传输。

namespace Home\Controller;
use Think\Controller;

class ChatapiController extends Controller {
    //多走了一步,做了个key处理,需要key值正确才能传入值,防止谁都可以插入数据
    public function _initialize(){
        
        $key = I('key');
        
        if($key!='ZCNZNB'){
            $this->error('key error');
        }
        
        
    }
    
    /*
    插入聊天信息,信息表
    */
    
  public function insertnews(){
      
      $data = [
          'send_user'=>I('send_user'),
          'msg'=>I('msg'),
          'create_time'=>date('Y-m-d H:m:s',time())
          ];
      
    $chat_news = M('chat_news');
    
    $check_news =  $chat_news->where("send_user='{$data['send_user']}'")->find();
    
         if(!$check_news){
       $chat_news->data($data)->add();
         }else{
          $id=$check_news['id'];
        $chat_news->data($data)->where("id=$id")->save();     
         }
     
      
      
      
  }
  
  //插入聊天新消息
  
  public function insertchat(){
      
          $chat = M('chat');
      
            $chat_data = [
          'send_user'=>I('send_user'),
          'msg'=>I('msg'),
          'customer'=>I('customer'),
          'add_time'=>date('Y-m-d H:m:s',time())
      ];

   $res = $chat->data($chat_data)->add();
      
      if($res){
          echo 1;
      }else{
          echo 0;
      }
      
  }


    
}

基本上这套内置客服聊天,我认为是比较简易的了。下面是数据库设计,设计了两个表
一个表是用来存储新消息的,防止看不见消息,一个表是用来存放聊天内容的。看着代码就能写出数据库设计。这款程序,是最简单的写法,并没有做一些处理,像是防XSS注入,等处理。大伙可以根据自己的需求,做出改变。也可以用这个方法,做聊天室,一对一聊天等好玩的功能。挺好玩的,大伙可以都尝试着去做。

 类似资料: