php教程

超轻量级php框架startmvc

基于swoole实现多人聊天室

更新时间:2020-03-28 15:11:05 作者:startmvc
本文实例为大家分享了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(); 
 } 
 
} 

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

swoole 聊天室