欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

基于swoole实现多人聊天室

程序员文章站 2022-06-14 11:52:49
本文实例为大家分享了swoole创建多人多房间聊天室的具体代码,供大家参考,具体内容如下 核心的swoole代码 基本的cs(client-sercer)结构不变,这里...

本文实例为大家分享了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(); 
  } 
 
} 

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