基于swoole实现多人聊天室
发布:smiling 来源: PHP粉丝网 添加日期:2021-10-01 16:33:22 浏览: 评论:0
本文实例为大家分享了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 (emptyempty($shuju['data'])) {
- $this->ws->push(Predis::getInstance()->get('fd'), $data);
- }else{
- if (emptyempty($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 (emptyempty($res)) {
- return "连接失败";
- }
- if (!emptyempty($this->data)) {
- //发送消息给server
- $rel=$cli->send(json_encode($this->data));
- }else{
- //发送消息给server
- $rel=$cli->send($this->msg);
- }
- if (!emptyempty($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();
- }
- }
Tags: swoole多人聊天室
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)