自定义TCP命令解析

EasySwoole支持用户进行自定义格式的命令解析与路由。以下我们将以最基础的例子作为讲解。

建立自定义命令解析类

namespace App\Sock;


use Core\Component\Socket\AbstractInterface\AbstractClient;
use Core\Component\Socket\AbstractInterface\AbstractCommandParser;
use Core\Component\Socket\Common\Command;

class Parser extends AbstractCommandParser
{

    function parser(Command $result, AbstractClient $client, $rawData)
    {
        // TODO: Implement parser() method.
    }
}

在AbstractCommandParser的接口定义中,我们需要实现parser方法,parser的三参数分别为:

  • 解析后的命令包
  • 客户端
  • 原始数据

比如,我现在定义的规则就是(命令,数据信息),那么我的解析规则就为:

function parser(Command $result, AbstractClient $client, $rawData)
{
     // TODO: Implement parser() method.
     $data = trim($rawData);
     $data = explode(',',$data);
     $result->setCommand(array_shift($data));
     $result->setMessage(array_shift($data));
}

定义命令注册类

namespace App\Sock;


use Core\Component\Socket\AbstractInterface\AbstractCommandRegister;
use Core\Component\Socket\Common\CommandList;

class Register extends AbstractCommandRegister
{

    function register(CommandList $commandList)
    {
        // TODO: Implement register() method.
    }
}

在AbstractCommandRegister接口中,我们必须实现register方法。举例,我们注册三个实验方法:

namespace App\Sock;


use Core\Component\Logger;
use Core\Component\Socket\AbstractInterface\AbstractCommandRegister;
use Core\Component\Socket\Client\TcpClient;
use Core\Component\Socket\Common\Command;
use Core\Component\Socket\Common\CommandList;
use Core\Component\Socket\Response;
use Core\Swoole\AsyncTaskManager;
use Core\Swoole\Server;

class Register extends AbstractCommandRegister
{

    function register(CommandList $commandList)
    {
        // TODO: Implement register() method.
        $commandList->addCommandHandler('hello',function (Command $request,TcpClient $client){
            $message = $request->getMessage();
            Logger::getInstance()->console('message is '.$message,false);
            AsyncTaskManager::getInstance()->add(function ()use($client){
                sleep(2);
                Response::response($client,"this is delay message for hello\n");
            });
            return "response for hello\n";
        });

        $commandList->addCommandHandler('close',function (Command $request,TcpClient $client){
            Response::response($client,"you are going to disconnect\n");
            Server::getInstance()->getServer()->close($client->getFd(),$client->getReactorId());
        });

        $commandList->setDefaultHandler(function (){
           return "unkown command\n";
        });
    }
}

添加事件监听

在EasySwoole的启动前事件中:

use App\Sock\Parser;
use App\Sock\Register;
use Core\Component\Socket\Dispatcher;


function beforeWorkerStart(\swoole_server $server){
    $listener = $server->addlistener('0.0.0.0',9502,SWOOLE_TCP);
    $listener->set(array(
        "open_eof_check"=>false,
        "package_max_length"=>2048,
    ));
    $listener->on("receive",function(\swoole_server $server,$fd,$from_id,$data){
         Dispatcher::getInstance(Register::class,Parser::class)->dispatchTCP($fd,$from_id,$data);
    });
}

测试

启动EasySwoole,执行:

telnet 127.0.0.1 9501

分别输入:

  • hello
  • hello,message
  • abc,
  • close

观察结果。

results matching ""

    No results matching ""