ThinkPHP8使用workerman

应用场景说明:通过建立通信,不同用户进行消息推送或数据更新,因为本身需要作为服务端进行主动消息推送,因此使用Gateway方式,如果不需要的可以不采用这种形式,以下内容仅为参考,具体业务场景,自行修改!!!!

废话少说,直接开干!!!

你可能会碰到以下问题,仅供参考!

一、可能会出现问题

1.GatewayWorker Not Support On Windows.

此问题出现在启用命令php think worker:gateway之后,需要使用自定义命令进行修改,具体下面细说

2.Implicit conversion from float 999996.9005584717 to int loses precision

此问题,在自定义命令后,需进行如下修改:\vendor\workerman\workerman\Events\Selelct.php第215行,

usleep($this->_selectTimeout); //    修改为下面usleep((int)$this->_selectTimeout);
二、不使用gateway

1.安装think-worker

composer require topthink/think-worker

2.运行命令

php think worker 运行httpphp think worker:server 运行webscoket //    默认是2345端口 

3.测试链接

// 新建一个html,直接复制以下代码,浏览器访问,打开控制台
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
</body>
<script>/*** 与GatewayWorker建立websocket连接,域名和端口改为你实际的域名端口,* 其中端口为Gateway端口,即start_gateway.php指定的端口。* start_gateway.php 中需要指定websocket协议,像这样* $gateway = new Gateway(websocket://0.0.0.0:7272);*/ws = new WebSocket("ws://127.0.0.1:2348");// 服务端主动推送消息时会触发这里的onmessagews.onopen = function () {// 触发系统自定义的test_event事件,发送json数据var data = {"type": "bind", "data": {"uid": "10001"}};ws.send(JSON.stringify(data));}ws.onmessage = function (e) {console.log(e.data);var data = {"type": "send", "data": {"uid": "10001", 'message': '呦吼'}};ws.send(JSON.stringify(data))}// ws.onmessage = onmessagews.onclose = function () {//  连接关闭,推送消息至服务端var data = {type: 'close', data: "{'uid':10001}"};ws.send(JSON.stringify(data));}</script>
</html>

4、效果截图

监听的方法,默认在config/worker_server.php里面,也可以通过继承Server进行修改,具体方法参考手册。tp-workerman

三、使用Gateway

如果直接使用 php think worker:gateway 就会提示GatewayWorker Not Support On Windows.具体原因简单说明(php think worker:gateway就是在同一个php文件里启动了多个worker,因为不能成功运行所以tp的命令行提前做了判定,显示不支持在windows下运行),大家自行搜一下具体原因即可。

具体解决思路,自定义命令进行运行,根据以下步骤进行参考

1.创建命令

php think make:command common@WorkerMain

2.复制以下代码到以上文件中

<?phpnamespace app\common\command;use GatewayWorker\BusinessWorker;
use GatewayWorker\Gateway;
use GatewayWorker\Register;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Config;
use Workerman\Worker;/*** Worker 命令行*/
class WorkerMain extends Command
{public function configure(){$this->setName('WorkerMain')->addArgument('service', Argument::OPTIONAL, 'workerman service: gateway|register|business_worker', null)->addOption('host', 'H', Option::VALUE_OPTIONAL, 'the host of workerman server.', null)->addOption('port', 'p', Option::VALUE_OPTIONAL, 'the port of workerman server.', null)->setDescription('GatewayWorker Server for ThinkPHP runs on Windows system');}/*** 由于windows下不支持下无法使用status、stop、reload、restart等命令。* 所以去掉status、stop、reload、restart、守护进程等命令。* 文档说明: https://www.workerman.net/doc/workerman/must-read.html** 命令使用:* php think worker:gateway_win register* php think worker:gateway_win business_worker* php think worker:gateway_win gateway** @param Input $input* @param Output $output* @return int|void|null*/public function execute(Input $input, Output $output){$service = $input->getArgument('service');$option = Config::get('gateway_worker');if ($input->hasOption('host')) {$host = $input->getOption('host');} else {$host = !empty($option['host']) ? $option['host'] : '0.0.0.0';}if ($input->hasOption('port')) {$port = $input->getOption('port');} else {$port = !empty($option['port']) ? $option['port'] : '2347';}$registerAddress = !empty($option['registerAddress']) ? $option['registerAddress'] : '127.0.0.1:1236';switch ($service) {case 'register':$this->register($registerAddress);break;case 'business_worker':$this->businessWorker($registerAddress, $option['businessWorker'] ?? []);break;case 'gateway':$this->gateway($registerAddress, $host, $port, $option);break;default:$output->writeln("<error>Invalid argument action:{$service}, Expected gateway|register|business_worker.</error>");exit(1);break;}Worker::runAll();}/*** 启动register* @access public* @param string $registerAddress* @return void*/public function register(string $registerAddress): void{// 初始化registernew Register('text://' . $registerAddress);}/*** 启动businessWorker* @access public* @param string $registerAddress registerAddress* @param array $option 参数* @return void*/public function businessWorker(string $registerAddress, array $option = []): void{// 初始化 bussinessWorker 进程$worker = new BusinessWorker();$this->option($worker, $option);$worker->registerAddress = $registerAddress;}/*** @note 返回Gateway对象* @param string $registerAddress 注册地址* @param string $host 服务地址* @param int $port 监听端口* @param array $option 参数* @return void*/public function gateway(string $registerAddress, string $host, int $port, array $option = []): void{// 初始化 gateway 进程if (!empty($option['socket'])) {$socket = $option['socket'];unset($option['socket']);} else {$protocol = !empty($option['protocol']) ? $option['protocol'] : 'websocket';$socket = $protocol . '://' . $host . ':' . $port;unset($option['host'], $option['port'], $option['protocol']);}$gateway = new Gateway($socket, $option['context'] ?? []);// 以下设置参数都可以在配置文件中重新定义覆盖$gateway->name = 'Gateway';$gateway->count = 4;$gateway->lanIp = '127.0.0.1';$gateway->startPort = 2000;$gateway->pingInterval = 5;$gateway->pingNotResponseLimit = 0;$gateway->pingData = '{"type":"ping"}';$gateway->registerAddress = $registerAddress;// 全局静态属性设置foreach ($option as $name => $val) {if (in_array($name, ['stdoutFile', 'daemonize', 'pidFile', 'logFile'])) {Worker::${$name} = $val;unset($option[$name]);}}$this->option($gateway, $option);}/*** 设置参数* @access protected* @param Worker $worker Worker对象* @param array $option 参数* @return void*/protected function option(Worker $worker, array $option = []){// 设置参数if (!empty($option)) {foreach ($option as $key => $val) {$worker->$key = $val;}}}
}

3.运行命令

//    需依次运行以下命令php think WorkerMain gatewayphp think WorkerMain business_workerphp think WorkerMain register

4.浏览器访问:端口需改成gateway端口,默认2348

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body></body>
<script>/*** 与GatewayWorker建立websocket连接,域名和端口改为你实际的域名端口,* 其中端口为Gateway端口,即start_gateway.php指定的端口。* start_gateway.php 中需要指定websocket协议,像这样* $gateway = new Gateway(websocket://0.0.0.0:7272);*/ws = new WebSocket("ws://127.0.0.1:2348");// 服务端主动推送消息时会触发这里的onmessagews.onopen = function () {// 触发系统自定义的test_event事件,发送json数据var data = {"type": "bind", "data": {"uid": "18317093686"}};ws.send(JSON.stringify(data));}ws.onmessage = onmessagews.onclose = function () {//  连接关闭,推送消息至服务端var data = {type: 'close', data: "{'uid':10001}"};ws.send(JSON.stringify(data));}// 服务端发来消息时function onmessage(e){console.log(e.data,123);var data = JSON.parse(e.data);switch(data['type']){// 服务端ping客户端case 'ping':ws.send('{"type":"pong"}');break;;// 登录 更新用户列表case 'login':var client_name = data['client_name'];if(data['client_list']){client_id = data['client_id'];client_name = '你';client_list = data['client_list'];}else{client_list[data['client_id']] = data['client_name'];}say(data['client_id'], data['client_name'],  client_name+' 加入了聊天室', data['time']);flush_client_list();console.log(data['client_name']+"登录成功");break;// 发言case 'say'://{"type":"say","from_client_id":xxx,"to_client_id":"all/client_id","content":"xxx","time":"xxx"}console.log(data['msg']);break;// 用户退出 更新用户列表case 'logout'://{"type":"logout","client_id":xxx,"time":"xxx"}say(data['from_client_id'], data['from_client_name'], data['from_client_name']+' 退出了', data['time']);delete client_list[data['from_client_id']];flush_client_list();}}
</script>
</html>

完成以上工作就可以顺利进行啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/61529.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【USB】CC检测

CC信号有两根线&#xff0c;CC1和CC2&#xff0c;大部分USB线&#xff08;不带芯片的线缆&#xff09;里面只有一根CC线&#xff0c;DFP可根据两根CC线上的电压&#xff0c;判断是否已经插入设备。通过判断哪根CC线上有下拉电阻来判断方向&#xff0c;下图的说明已经非常清晰。…

「一」HarmonyOS端云一体化概要

关于作者 白晓明 宁夏图尔科技有限公司董事长兼CEO、坚果派联合创始人 华为HDE、润和软件HiHope社区专家、鸿蒙KOL、仓颉KOL 华为开发者学堂/51CTO学堂/CSDN学堂认证讲师 开放原子开源基金会2023开源贡献之星 「目录」 「一」HarmonyOS端云一体化概要 「二」体验HarmonyOS端云一…

三种复制只有阅读权限的飞书网络文档的方法

大家都知道&#xff0c;飞书是一款功能强大的在线协作工具&#xff0c;可以帮助团队更高效地协作和沟通。越来越多的资料都在使用飞书文档&#xff0c;在使用飞书的过程中&#xff0c;发现很多文档没有复制权限&#xff0c;如果想要摘抄笔记&#xff0c;只能一个字一个字地敲出…

shell--第一次作业

1.接收用户部署的服务名称 # 脚本入口 read -p "请输入要部署的服务名称&#xff1a;" service_name 2.判断服务是否安装 # 判断服务是否安装 if rpm -q "$service_name" &>/dev/null; then echo "服务 $service_name 已安装。" 已…

【UE5】使用基元数据对材质传参,从而避免新建材质实例

在项目中&#xff0c;经常会遇到这样的需求&#xff1a;多个模型&#xff08;例如 100 个&#xff09;使用相同的材质&#xff0c;但每个模型需要不同的参数设置&#xff0c;比如不同的颜色或随机种子等。 在这种情况下&#xff0c;创建 100 个实例材质不是最佳选择。正确的做…

css水平居中+垂直居中

display:“flex”,position: “absolute”,top:“50%”,left:“50%”,transform: ‘translate(-50%, -50%)’

cesium for unity的使用

先聊聊导入 看到这里的因该能够知道&#xff0c;官网以及网上绝大多数的方法都导入不进来&#xff0c;那么解决方法如下: 两个链接&#xff1a;按照顺序依次下载这两个tgz和zip&#xff0c;其中tgz为主要部分&#xff0c;zip为示例工程项目 如果您要查看示例工程项目的话&am…

【网络】Socket编程TCP/UDP序列化和反序列化理解应用层(C++实现)Json::Value

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;计算机网络原理_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.基于Socket的UDP和TCP编程介绍 1.1 基本TCP客户—服务器程序设计基本框架 ​编辑1.2 基本UDP客户—服务器程序设计基本框…

Linux下安装NVIDIA显卡驱动(全流程通俗教程)

1、确认显卡型号 查明你的NVIDIA显卡型号&#xff0c;以确保下载驱动程序的版本&#xff1a; lspci | grep -i vga 2、下载NVIDIA驱动 前往官方网站&#xff1a;NVIDIA官网 选择显卡信息&#xff1a;使用下拉菜单选择正确的显卡型号、Linux操作系统和系统架构。 下载驱动…

VIM的下载使用与基本指令【入门级别操作】

VIM——超级文本编辑器 在当今时代&#xff0c;功能极其复杂的代码编辑器和集成开发环境&#xff08;IDE&#xff09;有很多。 但如果只想要一个超轻量级的代码编辑器&#xff0c;用于 Unix、C 或其他语言/系统&#xff0c;而不需要那些华而不实的功能&#xff0c;该怎么办呢&…

Xcode 项目内 OC 混编 Python,调用 Python 函数,并获取返回值(基于 python 的 c函数库)

1:新建 Xcode 工程 2:工程添加 Python.framework 1597052861430.jpg 3:在当前工程下新建一个名字为 googleT 的 python 文件(googleT.py) 1597052584962.jpg 在 googleT.py 文件内写入一个测试 python 函数 def lgf_translate( str ):var1 Hello World!print (str var1)retu…

[第五空间 2021]pklovecloud 详细题解

知识点: 构造POP链 PHP类的作用域 NULL强比较 目录穿越 源码如下: <?php include flag.php; class pkshow { function echo_name() { return "Pk very safe^.^"; } } class acp { protected $cinder; public $neutron;public $n…

elment-ui的折叠tree表单实现纯前端搜索,展开收起功能

好久没更新博客了~ 记录一下本次做的一个很扯的需求 纯前端去实现这个查询的功能,后台返回的是个数组对象,前端要给他包装成树结构先展示 之后参考代码路径src\views\goods\category\index.vue 需求描述: 搜索输入任何一个关键字,都会展开他的父级,两个栏目都包含了,那么两个父…

Redis面试篇笔记(持续更新)

一、redis主从集群 单节点redis的并发能力是由上限的&#xff0c;要进一步提高redis的并发能力可以搭建主从集群&#xff0c;实现读写分离&#xff0c;一主多从&#xff0c;主节点写数据&#xff0c;从节点读数据 部署redis主从节点的docker-compose文件命令解析 version: &q…

HTML5拖拽API学习 托拽排序和可托拽课程表

文章目录 前言拖拽API核心概念拖拽式使用流程例子注意事项综合例子&#x1f330; 可拖拽课程表拖拽排序 前言 前端拖拽功能让网页元素可以通过鼠标或触摸操作移动。HTML5 提供了标准的拖拽API&#xff0c;简化了拖放操作的实现。以下是拖拽API的基本使用指南&#xff1a; 拖拽…

06 —— Webpack优化—压缩过程

css代码提取后想要压缩 —— 使用css-minimizer-webpack-plugin插件 下载 css-minimizer-webpack-plugin 本地软件包 npm install css-minimizer-webpack-plugin --save-dev 配置 webpack.config.js 让webpack拥有该功能 const CssMinimizerPlugin require(css-minimizer-…

小熊派Nano接入华为云

一、华为云IoTDA创建产品 创建如下服务&#xff0c;并添加对应的属性和命令。 二、小熊派接入 根据小熊派官方示例代码D6完成了小熊派接入华为云并实现属性上传命令下发。源码&#xff1a;小熊派开源社区/BearPi-HM_Nano 1. MQTT连接代码分析 这部分代码在oc_mqtt.c和oc_mq…

形态学图像处理(Morphological Image Processing)

形态学图像处理(Morphological Image Processing) 前言 ‍ 本博客为个人总结数字图像处理一课所写&#xff0c;并给出适当的扩展和相应的demo。 写博客跟做 checkpoint​ 很像&#xff0c;毕竟个人还不能达到那种信手拈来的境界&#xff0c;忘了就是从零开始训练&#xff0…

[webgis 0基础到找工作]------JavaScript--DOM事件进阶 day10

1.事件流 事件流是对事件执行过程的描述&#xff0c;了解事件的执行过程有助于加深对事件的理解&#xff0c;提升开发实践中对事件运用的灵活度。 简言之&#xff0c;捕获阶段是【从父到子】的传导过程&#xff0c;冒泡阶段是【从子向父】的传导过程。 1.1捕获和冒泡 如果事件…

MATLAB图注意力网络GAT多标签图分类预测可视化

全文链接&#xff1a;https://tecdat.cn/?p38321 本示例展示了如何使用图注意力网络&#xff08;GATs&#xff09;对具有多个独立标签的图进行分类。当数据中的观测值具有带有多个独立标签的图结构时&#xff0c;可以使用GAT来预测未知标签观测值的标签&#xff08;点击文末“…