基于swoole实现多人聊天室


Posted in PHP onJune 14, 2018

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

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

PHP 相关文章推荐
php ajax 静态分页过程形式
Sep 02 PHP
PHP对象转换为数组函数(递归方法)
Feb 04 PHP
介绍一些PHP判断变量的函数
Apr 24 PHP
PHP变量内存分配问题记录整理
Nov 27 PHP
php实现图片添加水印功能
Feb 13 PHP
PHP小教程之实现链表
Jun 09 PHP
PHP关联数组实现根据元素值删除元素的方法
Jun 26 PHP
PHP的压缩函数实现:gzencode、gzdeflate和gzcompress的区别
Jan 27 PHP
使用PHP免费发送定时短信的实例
Oct 24 PHP
基于 Swoole 的微信扫码登录功能实现代码
Jan 15 PHP
php在windows环境下获得cpu内存实时使用率(推荐)
Feb 08 PHP
对php 判断http还是https,以及获得当前url的方法详解
Jan 15 PHP
PHP实现数组转JSon和JSon转数组的方法示例
Jun 14 #PHP
php实现微信公众平台发红包功能
Jun 14 #PHP
ThinkPHP3.2框架自定义配置和加载用法示例
Jun 14 #PHP
thinkPHP框架实现多表查询的方法
Jun 14 #PHP
php微信开发之关注事件
Jun 14 #PHP
thinkPHP框架动态配置用法实例分析
Jun 14 #PHP
php微信开发之谷歌测距
Jun 14 #PHP
You might like
php SQL防注入代码集合
2008/04/25 PHP
PHP var_dump遍历对象属性的函数与应用代码
2010/06/04 PHP
Zend Framework教程之分发器Zend_Controller_Dispatcher用法详解
2016/03/07 PHP
ThinkPHP模板Volist标签嵌套循环输出多维数组的方法
2016/03/23 PHP
PHP实现给定一列字符,生成指定长度的所有可能组合示例
2019/06/22 PHP
JavaScript设置FieldSet展开与收缩
2009/05/15 Javascript
jquery 单击li防止重复加载的实现代码
2010/12/24 Javascript
简约JS日历控件 实例代码
2013/07/12 Javascript
常用的JavaScript验证正则表达式汇总
2013/11/26 Javascript
table行随鼠标移动变色示例
2014/05/07 Javascript
nodejs npm package.json中文文档
2014/09/04 NodeJs
JavaScript解析json格式数据简单示例
2014/12/09 Javascript
javascript动态创建及删除元素的方法
2014/12/22 Javascript
JavaScript中Cookie操作实例
2015/01/09 Javascript
Windows系统中安装nodejs图文教程
2015/02/28 NodeJs
在JavaScript中处理数组之reverse()方法的使用
2015/06/09 Javascript
基于jQuey实现鼠标滑过变色(整行变色)
2015/12/07 Javascript
Node.js返回JSONP详解
2016/05/18 Javascript
bootstrap+jQuery 实现下拉菜单中复选框全选和全不选效果
2017/06/12 jQuery
JS实现电脑虚拟键盘打字测试
2020/06/24 Javascript
vue+openlayers绘制省市边界线
2020/12/24 Vue.js
[03:14]DOTA2斧王 英雄基础教程
2013/11/26 DOTA
详解Python中的join()函数的用法
2015/04/07 Python
详解Tensorflow数据读取有三种方式(next_batch)
2018/02/01 Python
Python 实现数据结构-循环队列的操作方法
2019/07/17 Python
Python数据可视化 pyecharts实现各种统计图表过程详解
2019/08/15 Python
pytorch绘制并显示loss曲线和acc曲线,LeNet5识别图像准确率
2020/01/02 Python
基于Python3.7.1无法导入Numpy的解决方式
2020/03/09 Python
CSS3用@font-face实现自定义英文字体
2013/09/23 HTML / CSS
解决img标签上下出现间隙的方法
2016/12/14 HTML / CSS
New Balance澳大利亚官网:运动鞋和健身服装
2019/02/23 全球购物
应届电子商务毕业自荐书范文
2014/02/11 职场文书
集中采购方案
2014/06/10 职场文书
合理化建议书范文
2015/09/14 职场文书
Python虚拟环境virtualenv是如何使用的
2021/06/20 Python
剑指Offer之Java算法习题精讲二叉树专项训练
2022/03/21 Java/Android