具体的上手体验流程 workerman手册 -> GatewayWorker手册 -> webman手册 -> webman-admin手册
刚上手的时候看到四个文档,不知道看哪个,感觉很迷茫。简单介绍下四个文档之间的关系。
比作一棵树,根茎枝干就是workerman,剩余的三个是其衍生作品,是叶子。
在webman中装webman-admin,装gateway,简单实现http请求长连接,推送消息
![在这里插入图片描述](https://img-blog.csdnimg.cn/7c1c65aaa2e44805aaca383bfb637f2b.png
tp6中的回调展示方法
namespace app\common;
use GatewayWorker\Lib\Gateway;
use Workerman\Lib\Timer;
class GatewayWorker
{
//php think worker:gateway
public static function onWebSocketConnect($client_id, $data)
{
//var_export($data);
$token = isset($data['get']['token']) ? $data['get']['token'] : '';
if (empty($token)) {
Gateway::sendToCurrentClient("token传参异常");
Gateway::closeClient($client_id);
return;
}
$redis = newRedis();
$user_info = $redis->hget('user_info', $token);
if (!$user_info) {
Gateway::sendToCurrentClient("非法token值");
Gateway::closeClient($client_id);
return;
}
//绑定uid
Gateway::bindUid($client_id, $token);
//开局给用户设置一个定时器id
Gateway::setSession($client_id, ['time_id' => 0]);
}
//{"type": "to_msg","data": {"id": 2,"msg": "你在家吗"}}
public static function onMessage($client_id, $data)
{
$result = json_decode($data, true);
if (empty($result) || !isset($result['type'])) {
Gateway::sendToClient($client_id, "请按规定传值");
return;
}
switch ($result['type']) {
//互发消息
case 'to_msg':
$is_online = Gateway::isUidOnline($result['data']['id']);
if ($is_online) {
Gateway::sendToUid($result['data']['id'], $result['data']['msg']);
} else {
Gateway::sendToClient($client_id, "用户id:" . $result['data']['id'] . "不在线");
}
break;
//定时器
case 'game':
if ($_SESSION['time_id'] > 0) {
return;
}
$count = 5;
//创建一个每秒执行一次的倒计时
$_SESSION['time_id'] = $time_id = Timer::add(1, function() use (&$time_id, &$count, &$client_id) {
$leave_time = $count--;
if ($leave_time <= 1) {
//倒计时结束,删除定时器
Timer::del($time_id);
Gateway::updateSession($client_id, ['time_id' => 0]);
//强制分配给y,y不在线分配给z
}
//给用户推送倒计时剩余秒数
Gateway::sendToClient($client_id, $leave_time);
//执行匹配规则
});
break;
//其余功能匹配
default:
Gateway::sendToClient($client_id, "其余功能未开放");
break;
}
}
public static function onClose($client_id)
{
//用户断开之后需要删除定时器
if (isset($_SESSION['time_id']) && $_SESSION['time_id'] > 0) {
Timer::del($_SESSION['time_id']);
}
}
}
tp6自定义command
declare(strict_types=1);
namespace app\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;
class GatewayCommand extends Command
{
protected function configure()
{
// windows下操作指令
$this->setName('win_gateway')
->addArgument('service', Argument::OPTIONAL, 'workerman service: gateway|register|businessworker', 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)
->addOption('daemon', 'd', Option::VALUE_OPTIONAL, 'Run the workerman server in daemon mode.')
->setDescription('Gateway Server for ThinkPHP in Windows');
}
protected 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 'businessworker':
$this->businessWorker($registerAddress, isset($option['businessWorker']) ? $option['businessWorker'] : []);
break;
case 'gateway':
$this->gateway($registerAddress, $host, $port, $option);
break;
default:
$output->writeln("Invalid argument action:{$service}, Expected gateway|register|businessworker . ");
exit(1);
break;
}
Worker::runAll();
}
/**
* 启动register
* @access public
* @param string $registerAddress
* @return void
*/
public function register($registerAddress)
{
// 初始化register
new Register('text://' . $registerAddress);
}
/**
* 启动businessWorker
* @access public
* @param string $registerAddress registerAddress
* @param array $option 参数
* @return void
*/
public function businessWorker($registerAddress, $option = [])
{
// 初始化 bussinessWorker 进程
$worker = new BusinessWorker();
$this->option($worker, $option);
$worker->registerAddress = $registerAddress;
}
/**
* 启动gateway
* @access public
* @param string $registerAddress registerAddress
* @param string $host 服务地址
* @param integer $port 监听端口
* @param array $option 参数
* @return void
*/
public function gateway($registerAddress, $host, $port, $option = [])
{
// 初始化 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, isset($option['context']) ? $option['context'] : []);
// 以下设置参数都可以在配置文件中重新定义覆盖
$gateway->name = 'Gateway';
$gateway->count = 4;
$gateway->lanIp = '127.0.0.1';
$gateway->startPort = 2000;
$gateway->pingInterval = 10;
$gateway->pingNotResponseLimit = 1;
$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, array $option = [])
{
// 设置参数
if (!empty($option)) {
foreach ($option as $key => $val) {
$worker->$key = $val;
}
}
}
}
windows.bat文件实现在windows下测试
start php think win_gateway register
start php think win_gateway businessworker
start php think win_gateway gateway
newredis
//公共方法
use think\facade\Config;
//redis
function newRedis($select = '')
{
$config = Config::get('cache.stores.redis');
$db = empty($config['select']) ? $config['select'] : $select;
$redis = new \Redis();
$redis->connect($config['host'], $config['port']);
if (!empty($config['password'])) {
$redis->auth($config['password']);
}
$redis->select($db);
return $redis;
}
config
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
return [
// 默认缓存驱动
'default' => env('cache.driver', 'file'),
// 缓存连接方式配置
'stores' => [
'file' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => '',
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
// 缓存标签前缀
'tag_prefix' => 'tag:',
// 序列化机制 例如 ['serialize', 'unserialize']
'serialize' => [],
],
// 配置Reids
'redis' => [
'type' => 'redis',
'host' => '127.0.0.1',
'port' => '6379',
'password' => '',
'select' => '0',
// 全局缓存有效期(0为永久有效)
'expire' => 0,
// 缓存前缀
'prefix' => '',
//默认缓存周期
'timeout' => 3600,
],
],
];