分享一个think-swoole实战案例【详细演示】
开始写事件中中方法
连接事件app/listener/SwWsConnect.php
public function handle($event, /think/swoole/websocket $ws)
{
// 获取当前发送者的fd
$fd = $ws->getSender();
echo "server: handshake success with fd{$fd}/n";
}
关闭事件app/listener/SwWsClose.php
public function handle($event, /think/swoole/websocket $ws)
{
$fd = $ws->getSender();
echo "client {$fd} closed/n";
}
message事件app/listener/SwWsMessage.php
public function handle($event, /think/swoole/websocket $ws)
{
$fd = $ws->getSender();
$data = json_encode($event);
echo "receive from {$fd}:{$data}/n";
$ws->emit("this is server", $fd);
}
启动php think swoole进行测试
think-swoole中的websocket方法总结
//给自己发消息
$ws->emit("this is server", $ws->getSender());
//给指定一个fd发消息
$ws->to($to)->emit("messagecallback",$data);
//给指定多个人发消息
$ws->to([1,2,3])->emit("messagecallback",$data);
//发送给所有的(不包含自己)
$ws->broadcast()->emit("messagecallback",$data);
//模拟formfd 给tofd 发送消息
$ws->setSender($formfd)->to($tofd)->emit("messagecallback",$data);
注意:在多个实时通讯场景下使用
emit第一个参数传入 传入 事件名称callback 例如
messagecallback
如果你发现你think-swoole中有些没有swoole中的方法可以这么干
$sw = app('swoole.server');
$sw = app("think/swoole/Manager")->getServer();
//以上二选一
$es = $sw->isEstablished($fd); //检查连接是否为有效的WebSocket客户端连接
var_dump($es);
聊天室room实现
前端文件参考 html/room.html 或 html/room-socket-io.html
php think make:listener SwRoomJoin php think make:listener SwRoomLeave php think make:listener SwRoomMessage
事件绑定
// 加入房间
'swoole.websocket.RoomJoin' => [
/app/listener/SwRoomJoin::class
],
// 离开房间
'swoole.websocket.Roomleave' => [
/app/listener/SwRoomLeave::class
],
// 在房间发消息
'swoole.websocket.RoomMessage' => [
/app/listener/SwRoomMessage::class
]
加入房间逻辑
public function handle($event, /think/swoole/websocket $ws, /think/swoole/websocket/room $room)
{
$fd = $ws->getSender();
//客户端假如定的room
$roomid = $event['room'];
//获取指定房间下有哪些客户端
$roomfds = $room->getClients($roomid);
// 判断这个房间有没有自己 如果有自己就不需要再次发送通知
if (in_array($fd, $roomfds)) {
$ws->to($roomfds)->emit("roomjoincallback", "房间{$roomid}已加入");
return;
}
//加入房间
$ws->join($roomid);
$ws->to($roomfds)->emit("roomjoincallback", "{$fd}加入房间{$roomid}成功");
}
离开房间逻辑
public function handle($event, /think/swoole/websocket $ws, /think/swoole/websocket/Room $room)
{
$roomid = $event['room'];
$fd = $ws->getSender();
$roomfds = $room->getClients($roomid);
if (!in_array($fd, $roomfds)) {
$ws->emit("roomleavecallback", "{$fd}不在{$roomid}房间内,怎么离开~");
return;
}
//离开房间
$ws->leave($roomid);
//获取当前客户端加入了哪些客户端
$rooms = $room->getRooms($fd);
$ws->to($roomfds)->emit("roomleavecallback", "{$fd}已离开了~~");
}
在房间发布聊天逻辑
public function handle($event, /think/swoole/websocket $ws, /think/swoole/websocket/room $room)
{
//
$roomid = $event['room'];
$text = $event['text'];
$fd = $ws->getSender();
$roomfds = $room->getClients($roomid);
if (!in_array($fd, $roomfds)) {
$ws->emit("roommessagecallback", "{$fd}不在{$roomid}房间内,无法进入发布聊天~");
return;
}
$ws->to($roomfds)->emit("roommessagecallback", $text);
}
事件订阅
php think make:listener SwSubscribe
applistenerSwSubscribe.php
ws = app('think/swoole/Websocket');
// }
public function __construct(/think/Container $c)
{
$this->ws = $c->make(/think/swoole/Websocket::class);
}
public function onConnect()
{
$fd = $this->ws->getSender();
echo "server: handshake success with fd{$fd}/n";
}
public function onClose()
{
$fd = $this->ws->getSender();
echo "client {$fd} closed/n";
}
public function onMessage($event)
{
$fd = $this->ws->getSender();
var_dump($event);
echo "server: handshake success with fd{$fd}/n";
$this->ws->emit("this is server", $fd);
}
}
有点类似 将原生的swoole代码改成面向对象代码,生效方法
config/swoole.php中在subscribe加入/app/listener/SwSubscribe::class'subscribe' => [ /app/listener/SwSubscribe::class ],在
app/event.php文件中的swoole.websocket.Connect相当于app/listener/SwSubscribe.php文件中的onConnect函数。如果同时存在的存在的话,就会向客户端发送2次以上的消息
Task任务投递
https://wiki.swoole.com/#/start/start_task
生成事件
php think make:listener SwSendEmailTask
编写发送邮件方法app/listener/SwSendEmailTask.php
public function handle($event)
{
var_dump($event);
//
echo "开发发送邮件".time();
sleep(3);
echo "结束发送邮件".time();
}
注册事件app/event.php
'swoole.task'=>[
/app/listener/SwSendEmailTask::class
],
在控制器中投递任务
public function doRegister()
{
$server = app('swoole.server');
$server->task(/app/listener/SwSendEmailTask::class);
return "注册成功";
}
public function doRegister(/think/swoole/Manager $manager)
{
$server = $manager->getServer();
$server->task(/app/listener/SwSendEmailTask::class);
return "注册成功";
}
public function doRegister(/Swoole/Server $server)
{
$server->task(/app/listener/SwSendEmailTask::class);
return "注册成功";
}
三种获取
/Swoole/Server,任意选其一
在swoole中还有一个事件叫finish,它的作用就是把异步任务的结果返回,在think-swool是这么处理的
定义一个发送邮件异步任务处理结果的事件
php think make:listener SwSendEmailFinish
注册事件app/event.php
'swoole.finish'=>[
/app/listener/SwSendEmailFinish::class
],
在task任务中调用
public function handle($event)
{
var_dump($event);
//
echo "开发发送邮件".time();
sleep(3);
echo "结束发送邮件".time();
$event->finish(/app/listener/SwSendEmailFinish::class);
}
高性能共享内存 Table
https://wiki.swoole.com/#/mem...
先定结构在进行操作数据(原生swoole操作)
$table = new Swoole/Table(1024);
//创建表
$table->column("id", Swoole/Table::TYPE_INT);
$table->column("name", Swoole/Table::TYPE_STRING);
$table->column("money", Swoole/Table::TYPE_FLOAT);
$table->create();
//添加数据
$table->set("zq", [
'id' => 1,
'name' => "zhiqiang",
'money' => 100,
]);
//获取一行数据
$table->get("zq");
// 修改数据
// 字段递增
$table->incr("zq","money",2);
//递减
$table->decr("zq","money",2);
// 返回 table 中存在的条目数。
$table->count();
//遍历table中的数据
foreach($table as $item){
var_dump($item);
}
think-swoole中的操作
先对table表结构进行初始化config/swoole.php
'tables' => [
'user'=>[
'size'=>1024,
'columns'=>[
[
'name'=>'id',
'type'=>/Swoole/Table::TYPE_INT
],
[
'name'=>'name',
'type'=>/Swoole/Table::TYPE_STRING,
'size'=>32
],
[
'name'=>'money',
'type'=>/Swoole/Table::TYPE_FLOAT
],
],
],
],
操作数据
$table = app('swoole.table.user');
$table->set("zq", [
'id' => 1,
'name' => "zhiqiang",
'money' => 100
]);
//获取一行数据
$table->get("zq");
// 修改数据
// 字段递增
$table->incr("zq", "money", 2);
//递减
$table->decr("zq", "money", 2);
// 返回 table 中存在的条目数。
$table->count();
//遍历table中的数据
foreach ($table as $item) {
var_dump($item);
}
// 检查 table 中是否存在某一个 key。
$table->exist('zq');
//获取实际占用内存尺寸,单位字节
$table->momorySize();
RPC
RPC(Remote Procedure Call):远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的思想。
详细介绍:https://developer.51cto.com/a...
- 解决分布式系统中,服务之间的调用问题。
- 远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑。
- 节点角色说明:
- Server: 暴露服务的服务提供方
- Client: 调用远程服务的服务消费方
- Registry: 服务注册与发现的注册中心
think-swoole实现RPC功能
服务器端
接口定义app/rpc/interfaces/UserInterface.php
实现接口
app/rpc/services/UserService.php注册rpc服务
config/swoole.php'rpc' => [ 'server' => [ //开启rpc服务 'enable' => true, //rpc端口 'port' => 9000, 'services' => [ //注册服务 /app/rpc/services/UserService::class ], ], // 如果填写也是可以调用其他服务端 'client' => [ ], ],启动服务端
php think swoole start / php think swoole:rpc客户端
'rpc' => [ 'server' => [ ], 'client' => [ 'tp6'=>[ //服务端的ip地址 'host'=>'127.0.0.1', //服务端对应的端口 'port'=>'9000' ] // 更多服务端 ], ],运行
php think rpc:interface生成RPC接口文件app/rpc.php['rpc/contract/tp6/UserInterface']];在控制器调用
public function index(/rpc/contract/tp6/UserInterface $user) { // $user->find(1); // $user->create(); }定时任务
在think-swoole 2.0版本的时候还是支持自定义定时任务配置,详细参考https://github.com/top-think/think-swoole/tree/2.0
在3.0就不支持了,在这里介绍一个通用的命令行启动定时任务
php think make:command SwooleTimer加载命令行
config/console.php'commands' => [ 'swooletimer'=>app/command/SwooleTimer::class ........... ],书写命令脚本
app/command/SwooleTimer.phpsetName('app/command/swooletimer') ->addArgument('action', Argument::OPTIONAL, "start | stop", 'start') ->setDescription('Swoole Timer for ThinkPHP'); } public function handle() { $action = $this->input->getArgument('action'); if (in_array($action, ['start','stopall'])) { $this->app->invokeMethod([$this, $action], [], true); } else { $this->output->writeln("Invalid argument action:{$action}, Expected start "); } } /** * 启动定时任务 主要任务计划在这里书写 */ protected function start() { // https://wiki.swoole.com/#/timer $timer_id=swoole_timer_tick(2000,function (){ echo "2s循环执行需要做的事情".time()."/n"; }); $this->output->writeln("Swoole Timer_id:{$timer_id} "); } /** * 清除所有的定时任务 */ protected function stop(){ swoole_timer_clear_all(); $this->output->writeln("Swoole Timer clear all ok"); } }以上就是分享一个think-swoole实战案例【详细演示】的详细内容,更多请关注毛票票其它相关文章!