ThinkPHP部署Workerman的成功使用示例
发布:smiling 来源: PHP粉丝网 添加日期:2023-10-06 17:07:07 浏览: 评论:0
本文介绍thinkphp中关于composer集成workerman的方法,并解决了安装过程 中遇到的错误,实现了和woerkman进行握手和通信的demo,用户可以在此基础上按自己的逻辑实现一个聊天系统或者客服系统。
一、安装扩展包 composer require topthink/think-worker
直接执行:composer require topthink/think-worker=1.0.* 即可成功
二、新建 server.php
- #!/usr/bin/env php
- <?php
- define('APP_PATH', __DIR__ . '/application/');
- define('BIND_MODULE','push/Worker');
- // 加载框架引导文件
- require __DIR__ . '/thinkphp/start.php';
三、新建Worker.php
php think make:controller push/Worker
即可,将里面的内容替换如下所示:
- <?php
- namespace app\push\controller;
- use think\Controller;
- use think\Request;
- use think\worker\Server;
- use think\Cache;
- class Worker extends Server
- {
- protected $socket = 'websocket://0.0.0.0:2346';
- protected $processes = 1;
- protected $uidConnections = array();
- static $count = 0;
- /**
- * 收到信息
- * @param $connection
- * @param $data
- */
- public function onMessage($connection, $data)
- {
- $retdata=json_decode($data,true);
- $uid=$retdata['id'];
- $message=$retdata['msg'];
- if(isset($this->uidConnections[$uid]))
- {
- $connection = $this->uidConnections[$uid];
- $connection->send($message);
- // return true;
- }
- $connection->send('我收到你的信息了333='.$retdata['msg']);
- }
- /**
- * 当连接建立时触发的回调函数
- * @param $connection
- */
- public function onConnect($connection)
- {
- $this->uidConnections[$connection->id] = $connection;
- $connection->send('你连接了我='.$connection->id);
- }
- // 针对uid推送数据
- public function sendMessageByUid($uid, $message)
- {
- if(isset($this->uidConnections[$uid]))
- {
- $connection = $this->uidConnections[$uid];
- $connection->send($message);
- return true;
- }
- return false;
- }
- /**
- * 当连接断开时触发的回调函数
- * @param $connection
- */
- public function onClose($connection)
- {
- }
- /**
- * 当客户端的连接上发生错误时触发
- * @param $connection
- * @param $code
- * @param $msg
- */
- public function onError($connection, $code, $msg)
- {
- echo "error $code $msg\n";
- }
- /**
- * 每个进程启动
- * @param $worker
- */
- public function onWorkerStart($worker)
- {
- }
- }
四、执行 php server.php start
遇到禁用函数就去对应的PHP里面把禁用函数删除 (此命令可以放到Supervisor的守护进程里面去),并且查看端口是否运行,宝塔里面也要放行对应的端口 2346
测试远程连接: telnet localhost 2346 localhost改成外网ip即可,这个走通了,前端就能直接连接了
linux 退出Telnet命令 先输入命令:CTRL+]然后再输入命令:quit
五、前端代码
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>Title</title>
- </head>
- <body>
- <script>
- ws = new WebSocket("ws://118.**.***.207:2346");
- ws.onopen = function() {
- console.log("连接成功");
- ws.send('tom');
- console.log("给服务端发送一个字符串:tom");
- };
- ws.onmessage = function(e) {
- console.log("收到服务端的消息:" + e.data);
- };
- </script>
- </body>
- </html>
六、前端开两个端口即可进行相互通讯:
ws.send('{"id":"2","msg":"21111111111110"}');
重点在这:因为在这里需要用到服务端给客户端推送,用到了text服务
WorkerMan中php后端及时推送消息给客户端
原理:
1、建立一个websocket Worker,用来维持客户端长连接
2、websocket Worker内部建立一个text Worker
3、websocket Worker 与 text Worker是同一个进程,可以方便的共享客户端连接
4、某个独立的php后台系统通过text协议与text Worker通讯
5、text Worker操作websocket连接完成数据推送
代码及步骤
- //push.php
- <?php
- use Workerman\Worker;
- require_once './vendor/workerman/workerman/Autoloader.php';
- // 初始化一个worker容器,监听1234端口
- $worker = new Worker('websocket://0.0.0.0:1234');//
- /*
- * 注意这里进程数必须设置为1,否则会报端口占用错误
- * (php 7可以设置进程数大于1,前提是$inner_text_worker->reusePort=true)
- */
- $worker->count = 1;
- // worker进程启动后创建一个text Worker以便打开一个内部通讯端口
- $worker->onWorkerStart = function($worker)
- {
- // 开启一个内部端口,方便内部系统推送数据,Text协议格式 文本+换行符
- $inner_text_worker = new Worker('text://0.0.0.0:5678');
- $inner_text_worker->onMessage = function($connection, $buffer)
- {
- // $data数组格式,里面有uid,表示向那个uid的页面推送数据
- $data = json_decode($buffer, true);
- $uid = $data['uid'];
- // 通过workerman,向uid的页面推送数据
- $ret = sendMessageByUid($uid, $buffer);
- // 返回推送结果
- $connection->send($ret ? 'ok' : 'fail');
- };
- // $connection->send('你好,你连接我了');
- // ## 执行监听 ##
- $inner_text_worker->listen();
- };
- // 新增加一个属性,用来保存uid到connection的映射
- $worker->uidConnections = array();
- // 当有客户端发来消息时执行的回调函数
- $worker->onMessage = function($connection, $data)
- {
- $data=json_decode($data,true);
- $connection->send('99897');
- global $worker;
- // 判断当前客户端是否已经验证,既是否设置了uid
- if(!isset($connection->uid))
- {
- // 没验证的话把第一个包当做uid(这里为了方便演示,没做真正的验证)
- $connection->uid = $data['id'];
- /* 保存uid到connection的映射,这样可以方便的通过uid查找connection,
- * 实现针对特定uid推送数据
- */
- $worker->uidConnections[$connection->uid] = $connection;
- $connection->send('9980'.$data['msg']);
- return;
- }else{
- $connection->send('998123');
- }
- };
- // 当有客户端连接断开时
- $worker->onClose = function($connection)
- {
- global $worker;
- if(isset($connection->uid))
- {
- // 连接断开时删除映射
- unset($worker->uidConnections[$connection->uid]);
- }
- };
- // 向所有验证的用户推送数据
- function broadcast($message)
- {
- global $worker;
- foreach($worker->uidConnections as $connection)
- {
- $connection->send($message);
- }
- }
- // 针对uid推送数据
- function sendMessageByUid($uid, $message)
- {
- global $worker;
- if(isset($worker->uidConnections[$uid]))
- {
- $connection = $worker->uidConnections[$uid];
- $connection->send($message);
- return true;
- }
- return false;
- }
运行所有的worker
Worker::runAll();
启动后端服务 php push.php start -d
前端接收推送的js代码
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>Title</title>
- </head>
- <body>
- <script>
- var ws = new WebSocket('ws://118.**.**.207:1234');
- ws.onopen = function(){
- var uid = 'uid1';
- ws.send(uid);
- console.log("给服务端发送一个字符串:"+uid);
- };
- ws.onmessage = function(e){
- // alert(e.data);
- console.log("收到服务端的消息:" + e.data);
- };
- </script>
- </body>
- </html>
后端推送消息的代码
- // 建立socket连接到内部推送端口
- $client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1);
- // 推送的数据,包含uid字段,表示是给这个uid推送
- $data = array('uid'=>'uid1', 'percent'=>'88%');
- // 发送数据,注意5678端口是Text协议的端口,Text协议需要在数据末尾加上换行符
- fwrite($client, json_encode($data)."\n");
- // 读取推送结果
- echo fread($client, 8192);
后端推送消息的代码和push.php监听同一个端口
push.php和前端监听同一个websocket端口
通过后端推送消息的代码向push.php推送数据,push.php接受到数据后通过处理 利用websocket往前端推送数据
Tags: Workerman
- 上一篇:windows服务器使用IIS时thinkphp搜索中文无效问题
- 下一篇:最后一页
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)