6、Workerman 基本使用 - Worker 属性与接口 >
hi,我是温新,一名 PHPer
本篇文章对 Worker 的属性进行基本的演示使用,这这些属性的详细信息请参考文档。
Worker 属性
<?php
/**
* worker-attribute.php
*
* Worker 属性
*/
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('tcp://0.0.0.0:8888');
// 设置日志文件
Worker::$logFile = '/tmp/workerman.log';
// 设置启动进程数量
$worker->count = 5;
// 设置进程名称
$worker->name = 'workerman-server';
$worker->onWorkerStart = function(Worker $worker)
{
// 当前 worker 进程的 id 编号
echo 'Worker 进程 ID:' .$worker->id . PHP_EOL;
// 定时,每10秒一次
Timer::add(10, function() use ($worker) {
// 遍历当前进程所有的客户端连接,发送当前服务器的时间
foreach($worker->connections as $connection) {
$connection->send(time());
}
});
};
$worker->onMessage = function (TcpConnection $connection, $data) {
};
Worker::runAll();
测试
$ php worker-attribute.php start
Workerman[worker-attribute.php] start in DEBUG mode
------------------------------------------- WORKERMAN -------------------------------------------
Workerman version:4.1.15 PHP version:8.2.0 Event-Loop:\Workerman\Events\Event
-------------------------------------------- WORKERS --------------------------------------------
proto user worker listen processes status
tcp codeing workerman-server tcp://0.0.0.0:8888 5 [OK]
-------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
Worker 进程 ID:0
Worker 进程 ID:1
Worker 进程 ID:2
Worker 进程 ID:3
Worker 进程 ID:4
查看下指定位置的日志文件
$ cat /tmp/workerman.log
2024-02-28 14:02:56 pid:51910 Workerman[worker-attribute.php] start in DEBUG mode
2024-02-28 14:03:28 pid:51910 Workerman[worker-attribute.php] stopping ...
2024-02-28 14:03:28 pid:51910 Workerman[worker-attribute.php] has been stopped
2024-02-28 14:04:33 pid:52191 Workerman[worker-attribute.php] start in DEBUG mode
2024-02-28 14:04:47 pid:52191 Workerman[worker-attribute.php] stopping ...
2024-02-28 14:04:47 pid:52191 Workerman[worker-attribute.php] has been stopped
2024-02-28 14:05:31 pid:52306 Workerman[worker-attribute.php] start in DEBUG mode
2024-02-28 14:05:38 pid:52331 Workerman[worker-attribute.php] reload
2024-02-28 14:05:38 pid:52306 Workerman[worker-attribute.php] reloading
2024-02-28 14:15:07 pid:52306 Workerman[worker-attribute.php] stopping ...
2024-02-28 14:15:07 pid:52306 Workerman[worker-attribute.php] has been stopped
2024-02-28 14:15:08 pid:53709 Workerman[worker-attribute.php] start in DEBUG mode
查看下进行名称
$ ps aux | grep workerman-server | awk '{print $14}'
workerman-server
workerman-server
workerman-server
workerman-server
workerman-server
Worker 接口
根据文档中的案例,来演示 listen
接口。
这个案例是文档中的案例,最重要的是,要去理解这个思路。
<?php
/**
* worker-list.php
*
* listen 监听
*/
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('websocket://0.0.0.0:1234');
// 注意这里进程数必须设置为 1
$worker->count = 1;
// worker 进程启动后创建一个 text Worker 以便打开一个内部通讯端口
$worker->onWorkerStart = function(Worker $worker) {
// 开启一个内部端口,方便内部系统推送数据,Text 协议格式 文本+换行符
$inner_text_worker = new Worker('text://0.0.0.0:5678');
$inner_text_worker->onMessage = function(TcpConnection $connection, $data) use ($worker) {
// $dataArr 数组格式,里面有 uid,表示向那个 uid 的页面推送数据
$dataArr = json_decode($data, true);
$uid = $dataArr['uid'];
// 通过 workerman,向 uid 的页面推送数据
$ret = sendMessageByUid($worker, $uid, $data);
// 返回推送结果
$connection->send($ret ? 'ok' : 'fail');
};
// 执行监听
$inner_text_worker->listen();
};
// 新增加一个属性,用来保存 uid 到 connection 的映射
$worker->uidConnections = [];
// 当有客户端发来消息时执行的回调函数
$worker->onMessage = function(TcpConnection $connection, $data) use ($worker) {
// 判断当前客户端是否已经验证,既是否设置了uid
if(!isset($connection->uid)) {
// 没验证的话把第一个包当做 uid(这里为了方便演示,没做真正的验证)
$connection->uid = $data;
/* 保存 uid 到 connection 的映射,这样可以方便的通过 uid 查找 connection,
* 实现针对特定 uid 推送数据
*/
$worker->uidConnections[$connection->uid] = $connection;
return;
}
};
// 当有客户端连接断开时
$worker->onClose = function(TcpConnection $connection) use ($worker) {
if(isset($connection->uid)){
// 连接断开时删除映射
unset($worker->uidConnections[$connection->uid]);
}
};
// 针对uid推送数据
function sendMessageByUid($worker, $uid, $message) {
// 如果 uid 存在于映射表中,则找到对应的连接并向其发送消息
if(isset($worker->uidConnections[$uid])) {
$webConnection = $worker->uidConnections[$uid];
$webConnection->send($message);
return true;
}
return false;
}
Worker::runAll();
代码解释:
- 创建一个 WebSocket 服务器,监听 1234 端口,用于处理客户端的 WebSocket 连接请求。
- 在 WebSocket 服务器启动时,创建一个内部通讯 Worker,监听 5678 端口,接收内部系统推送的消息,并通过 uid 将消息转发给相应的 WebSocket 客户端。
- 维护一个 uid 到连接的映射表,以便能够通过 uid向 特定用户推送消息。
- 提供
sendMessageByUid
函数,实现根据 uid 查找对应连接并发送消息的功能。
1、启动服务端
$ php worker-list.php start
2、前段接收推送的 JS 代码(可在 F12 中打开执行)
let ws = new WebSocket('ws://127.0.0.1:1234');
ws.onopen = function(){
let uid = 'uid1';
ws.send(uid);
};
ws.onmessage = function(e){
alert(e.data);
};
3、后端推送代码
<?php
// client.php
// 建立socket连接到内部推送端口
$client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1);
// 推送的数据,包含uid字段,表示是给这个uid推送
$data = ['uid'=>'uid1', 'percent'=>'88%'];
// 发送数据,注意5678端口是Text协议的端口,Text协议需要在数据末尾加上换行符
fwrite($client, json_encode($data)."\n");
// 读取推送结果
echo fread($client, 8192);
请登录后再评论