TCP 控制器

优质
小牛编辑
130浏览
2023-12-01

定义

<?php
namespace ImiDemo\TcpDemo\MainServer\Controller;

use Imi\ConnectContext;
use Imi\Server\Route\Annotation\Tcp\TcpRoute;
use Imi\Server\Route\Annotation\Tcp\TcpAction;
use Imi\Server\Route\Annotation\Tcp\TcpController;

/**
 * 数据收发测试
 * @TcpController
 */
class Test extends \Imi\Controller\TcpController
{
    /**
     * 登录
     * 
     * @TcpAction
     * @TcpRoute({"action"="login"})
     * @return void
     */
    public function login($data)
    {
        ConnectContext::set('username', $data->username);
        $this->server->joinGroup('g1', $this->data->getFd());
        return ['action'=>'login', 'success'=>true];
    }
}

首先控制器类必须有@TcpController注解,对应动作必须有@TcpAction@TcpRoute注解。

注解

@TcpRoute

指定 Tcp 路由解析规则。

// 解析 $data['action'] === 'login'
@TcpRoute({"action"="login"})
// 解析 $data['a']['b']['c'] === 'login'
@TcpRoute({"a.b.c"="login"})
// 解析 $data['a'] == '1' && $data['b'] == '2'
@TcpRoute({"a"="1", "b"="2"})

当然对象也是支持的:

// 解析 $data->a->b->c === 'login'
@TcpRoute({"a.b.c"="login"})

路由匹配成功,就会执行这个动作。

动作响应数据

响应当前这个请求

直接在方法中返回一个数组或对象,在服务器配置设定的处理器,就会把这个转为对应数据响应给客户端。

配置文件

return [
    // 主服务器配置,提供websocket服务
    'mainServer'    =>    [
        'namespace'    =>    'ImiDemo\TcpDemo\MainServer',
        'type'        =>    Type::TCP_SERVER,
        // 'host'        =>    '0.0.0.0',
        'port'        =>    8085,
        // 'mode'        =>    SWOOLE_BASE,
        // 'sockType'    =>    SWOOLE_SOCK_TCP,
        'configs'    =>    [
            'reactor_num'        =>    2,
            'worker_num'        =>    2,
            'task_worker_num'    =>    8,
            // EOF自动分包
            'open_eof_split'    =>    true, //打开EOF_SPLIT检测
            'package_eof'        =>    "\r\n", //设置EOF
        ],
        // 数据处理器
        'dataParser'    =>    \ImiDemo\TcpDemo\MainServer\Parser\JsonObjectParser::class,
    ],
}

响应数据

return ['success'=>true];

分组发送

$this->server->groupCall('组名', 'push', ['success'=>true]);

当然,并不是每个请求都需要有响应数据,什么都不return或者return null就是不响应数据。

指定连接发送数据

以下代码写在控制器的代码中,总而言之,如果你要推送消息,你得拿到SwooleServer对象。

// $server 对象是 \Swoole\Server类型
$server = $this->server->getSwooleServer();
// 指定连接
$fd = 19260817;
$data = 'hello imi';

// 原样发送数据
$server->send($fd, $data);

// 使用预定义的编码器,编码后发送数据
$server->send($fd, $this->encodeMessage($data));

类属性

$server

方法

getSwooleServer

获取Swoole的Server对象

/**
 * 组是否存在
 *
 * @param string $groupName
 * @return boolean
 */
public function hasGroup(string $groupName);
/**
 * 创建组,返回组对象
 *
 * @param string $groupName
 * @param integer $maxClients
 * @return \Imi\Server\Group\Group
 */
public function createGroup(string $groupName, int $maxClients = -1);
/**
 * 获取组对象,不存在返回null
 *
 * @param string $groupName
 * @return \Imi\Server\Group\Group|null
 */
public function getGroup(string $groupName);
/**
 * 加入组,组不存在则自动创建
 *
 * @param string $groupName
 * @param integer $fd
 * @return void
 */
public function joinGroup(string $groupName, int $fd);
/**
 * 离开组,组不存在则自动创建
 *
 * @param string $groupName
 * @param integer $fd
 * @return void
 */
public function leaveGroup(string $groupName, int $fd);
/**
 * 调用组方法
 *
 * @param string $groupName
 * @param string $methodName
 * @param mixed ...$args
 * @return array
 */
public function groupCall(string $groupName, string $methodName, ...$args);
/**
 * 获取所有组列表
 *
 * @return \Imi\Server\Group\Group[]
 */
public function getGroups(): array;

$data

方法

/**
 * 获取客户端的socket id
 * @return int
 */
public function getFd(): int;
/**
 * 数据内容,可以是文本内容也可以是二进制数据,可以通过opcode的值来判断
 * @return string
 */
public function getData();
/**
 * 获取格式化后的数据,一般是数组或对象
 * @return mixed
 */
public function getFormatData();
/**
 * 获取Reactor线程ID
 *
 * @return int
 */
public function getReactorID(): int;

控制器类方法

encodeMessage

/**
 * 编码消息,把数据编码为发送给客户端的格式
 *
 * @param mixed $data
 * @return mixed
 */
protected function encodeMessage($data)