zoukankan      html  css  js  c++  java
  • 基于swoole实现多人聊天室

    核心的swoole代码

    基本的cs(client-sercer)结构不变,这里利用的是redis的哈希和set来储存和分组;从而达到了分组,统计,定时推送等功能;最后利用onclose事件来剔除断开的连接,全部代码如下:(没做前端,就不展示了)

    核心的swoole ws.php

    <?php 
      
    namespace appcommon; 
    require_once 'Predis.php'; 
    require_once 'Task.php'; 
    /** 
    *  socket面向对象的编译 
    */
    class Ws 
    { 
      CONST HOST='0.0.0.0'; 
      CONST PORT='9501'; 
      public $ws=null; 
      public $getmsg=null; 
      public $server=null; 
      
      public function __construct() 
      {   
        $this->ws=new swoole_websocket_server(self::HOST,self::PORT); 
        $this->ws->set([ 
          //启动task必须要设置其数量 
          'worker_num' => 4, 
          'task_worker_num' => 2, 
          // 'heartbeat_check_interval' => 5, 
          // 'heartbeat_idle_time' => 10, 
        ]); 
        //监听新端口 
        $this->server=$this->ws->listen("127.0.0.1", 9502, SWOOLE_SOCK_TCP); 
        //关闭websocket模式 
        $this->server->set([ 
          'open_websocket_protocol' => false, 
        ]); 
      
        $this->ws->on("start", [$this, 'onStart']); 
        $this->ws->on('open',[$this,'onopen']); 
        $this->server->on("receive", [$this, 'onReceive']); 
        $this->ws->on('task',[$this,'onTask']); 
        $this->ws->on('finish',[$this,'onFinish']); 
        $this->ws->on('message',[$this,'onmessage']); 
        $this->ws->on('close',[$this,'onclose']); 
        $this->server->on("close", [$this, 'oncloses']); 
        $this->ws->start(); 
      } 
      //监听数据接收事件 
      public function onReceive($serv, $fd, $from_id, $data) 
      { 
        $shuju=json_decode($data,ture); 
        // print_r($shuju).PHP_EOL; 
        if (empty($shuju['data'])) { 
          $this->ws->push(Predis::getInstance()->get('fd'), $data); 
        }else{ 
          if (empty($shuju['msg'])) { 
            //执行异步任务 
            $this->ws->task($shuju); 
          }else{ 
            $push_arr=Predis::getInstance()->hvals($shuju['data']); 
            // echo "集群是:".print_r($push_arr); 
            foreach ($push_arr as $v) { 
              $this->ws->push($v, $shuju['msg']); 
            } 
          } 
        } 
      } 
      /** 
       * 设置进程名,为后续平滑重启进程 
       * @param $server 
       */
      public function onStart($server) { 
        swoole_set_process_name("live_master"); 
      }    
      /** 
        监听开启事件的回调 
      */
      public function onopen($server, $request) 
      { 
        print_r("这时的fd是:",$request->fd); 
        Predis::getInstance()->set('fd',$request->fd); 
      } 
        
      /** 
        监听接收事件的回调 
      */
      public function onmessage($server, $frame) 
      { 
        $server->push($frame->fd, "{$frame->data}"); 
      } 
      /** 
        监听关闭事件的回调 
      */
      public function onclose($ser, $fd) 
      { 
        print_r("你好,我的{$fd}
    "); 
        //退出并删除多余的分组fd 
        $group=Predis::getInstance()->sMembers('group'); 
        foreach ($group as $v) { 
          $fangjian=Predis::getInstance()->hgetall($v); 
          foreach ($fangjian as $k => $vv) { 
            if ($fd == $vv) { 
              Predis::getInstance()->hdel($v,$k); 
            } 
          } 
        } 
      } 
      public function oncloses($ser, $fd) 
      { 
        print_r("这个是client{$fd}
    "); 
      } 
      
      /** 
      *  $serv      服务 
      *  $task_id    任务ID,由swoole扩展内自动生成,用于区分不同的任务 
      *  $src_worker_id $task_id和$src_worker_id组合起来才是全局唯一的,不同的worker进程投递的任务ID可能会有相同 
      *  $data      是任务的内容 
      */
       public function onTask($serv,$task_id,$src_worker_id,$data) 
      { 
        //引入任务 
        $obj = new Task; 
        $method = $data['data']; 
        $arr = $data['arr']; 
        //发布具体的任务 
        $flag = $obj->$method($arr, $serv); 
        return $flag; // 告诉worker 
      } 
      /** 
      *  $task_id    是任务的ID 
      *  $data      是任务处理的结果内容 
      */
       public function onFinish($serv,$task_id,$data) 
      { 
        print_r($data).'/n'; 
      } 
      
    } 
      
    new Ws(); 

    分发任务task.php

    <?php 
    /** 
     * 代表的是 swoole里面 后续 所有 task异步 任务 都放这里来 
     * Date: 18/3/27 
     * Time: 上午1:20 
     */
    namespace appcommon; 
    // include 'Predis.php'; 
      
    class Task { 
      //异步创建房间 
      public function chuangjian($data,$serv) 
      { 
        $time=$data['time']*1000; 
        swoole_timer_after($time, function() use($data){ 
          //创建房间(修改拍卖商品状态) 
          self::post("https://code.77wx.cn/index/index/in"); 
        }); 
      } 
      
      //进入房间并缓存信息 
      public function jingru($data,$serv) 
      { 
        $fd=Predis::getInstance()->get('fd'); 
        //加入分组 
        Predis::getInstance()->hset($data['name'],$data['uid'],$fd); 
        //加入组集合 
        Predis::getInstance()->sadd('group',$data['name']); 
      } 
      
      
      public function post($url,$params=false,$ispost=0) 
      { 
        $httpInfo = array(); 
        $ch = curl_init(); 
        curl_setopt( $ch, CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1 ); 
        curl_setopt( $ch, CURLOPT_USERAGENT , 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22' ); 
        curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT , 30 ); 
        curl_setopt( $ch, CURLOPT_TIMEOUT , 30); 
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER , true ); 
        if( $ispost ) 
        { 
          curl_setopt( $ch , CURLOPT_POST , true ); 
          curl_setopt( $ch , CURLOPT_POSTFIELDS , $params ); 
          curl_setopt( $ch , CURLOPT_URL , $url ); 
        } 
        else
        { 
          if($params){ 
            curl_setopt( $ch , CURLOPT_URL , $url.'?'.$params ); 
          }else{ 
            curl_setopt( $ch , CURLOPT_URL , $url); 
          } 
        } 
        //执行 
        $response = curl_exec( $ch ); 
        if ($response === FALSE) { 
          //echo "cURL Error: " . curl_error($ch); 
          return false; 
        } 
      
        $httpCode = curl_getinfo( $ch , CURLINFO_HTTP_CODE ); 
        $httpInfo = array_merge( $httpInfo , curl_getinfo( $ch ) ); 
        //关闭url请求 
        curl_close( $ch ); 
        return json_decode($response,1); 
      } 
      
    }

    客户端 client.php

    <?php 
    namespace appcommon; 
      
    class Client 
    { 
      public $msg=''; 
      
      public $data=[]; 
      
      public function lianjie(){ 
      
        $cli = new swoole_client(SWOOLE_SOCK_TCP); 
        //判断连接状态(同步连接模式) 
        $res=$cli->connect('127.0.0.1', 9502); 
        if (empty($res)) { 
          return "连接失败"; 
        } 
      
        if (!empty($this->data)) { 
          //发送消息给server 
          $rel=$cli->send(json_encode($this->data)); 
        }else{ 
          //发送消息给server 
          $rel=$cli->send($this->msg); 
        } 
        if (!empty($rel)) { 
          return $rel; 
        }else{ 
          return flash; 
        } 
      } 
    }

    控制器index.php

    <?php 
    namespace appindexcontroller; 
      
    use appcommonClient; 
    use appcommonPredis; 
    use appcommonSql; 
    use appindexmodelUser; 
      
    class Index 
    { 
      //创建房间(添加拍卖倒计时) 
      public function chuangjian() 
      { 
        $data['time']=input("time"); 
        $data['id']=input("id"); 
        $cli = new Client(); 
        $cli->data = [ 
          'data' => 'chuangjian', 
          'arr' => $data
        ]; 
        return $cli->lianjie(); 
      } 
      //点击添加哈希(进入房间) 
      public function jingru() 
      { 
        $data['name']=input("name"); 
        $data['uid']=input("uid"); 
        $cli = new Client(); 
        $cli->data = [ 
          'data' => 'jingru', 
          'arr' => $data
        ]; 
        return $cli->lianjie(); 
      } 
      //本房间推送(出价格成功并推送) 
      public function pushfan() 
      { 
        $data['fan']=input("fan"); 
        $cli = new Client(); 
        $cli->data = [ 
          'data' => $data['fan'], 
          'msg' => "恭喜用户111,喜当爹!!!!"
        ]; 
        return $cli->lianjie(); 
      } 
      //时间结束并指定推送 
      public function zhiding() 
      { 
        $data['fan']=input("fan"); 
        $cli = new Client(); 
        $cli->data = [ 
          'data' => $data['fan'], 
          'msg' => "恭喜用户111,喜当爹!!!!"
        ]; 
        return $cli->lianjie(); 
      } 
      
    }

    完事!

  • 相关阅读:
    文件拖拽上传
    30天自制操作系统笔记(第三天)
    PAT 1040到底有几个pat
    pat 1039 到底买不买
    pat 1038 统计同成绩学生
    pat 乙级1034
    pat 乙级1022
    pat 乙级1009
    pat 乙级1008
    pat 乙级1002
  • 原文地址:https://www.cnblogs.com/wadhf/p/11827834.html
Copyright © 2011-2022 走看看