基于swoole实现多人聊天室

本文实例为大家分享了swoole创建多人多房间聊天室的具体代码,供大家参考,具体内容如下

核心的swoole代码

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

核心的swoole ws.php

<?php 
 
namespace app\\common; 
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}\\n\"); 
    //退出并删除多余的分组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}\\n\"); 
  } 
 
  /** 
  *  $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 app\\common; 
// 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 app\\common; 
 
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 app\\index\\controller; 
 
use app\\common\\Client; 
use app\\common\\Predis; 
use app\\common\\Sql; 
use app\\index\\model\\User; 
 
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(); 
  } 
 
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持免费资源网。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容