自定义TCP命令解析

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

建立自定义命令解析类

  1. namespace App\Sock;
  2. use Core\Component\Socket\AbstractInterface\AbstractClient;
  3. use Core\Component\Socket\AbstractInterface\AbstractCommandParser;
  4. use Core\Component\Socket\Common\Command;
  5. class Parser extends AbstractCommandParser
  6. {
  7. function parser(Command $result, AbstractClient $client, $rawData)
  8. {
  9. // TODO: Implement parser() method.
  10. }
  11. }

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

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

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

  1. function parser(Command $result, AbstractClient $client, $rawData)
  2. {
  3. // TODO: Implement parser() method.
  4. $data = trim($rawData);
  5. $data = explode(',',$data);
  6. $result->setCommand(array_shift($data));
  7. $result->setMessage(array_shift($data));
  8. }

定义命令注册类

  1. namespace App\Sock;
  2. use Core\Component\Socket\AbstractInterface\AbstractCommandRegister;
  3. use Core\Component\Socket\Common\CommandList;
  4. class Register extends AbstractCommandRegister
  5. {
  6. function register(CommandList $commandList)
  7. {
  8. // TODO: Implement register() method.
  9. }
  10. }

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

  1. namespace App\Sock;
  2. use Core\Component\Logger;
  3. use Core\Component\Socket\AbstractInterface\AbstractCommandRegister;
  4. use Core\Component\Socket\Client\TcpClient;
  5. use Core\Component\Socket\Common\Command;
  6. use Core\Component\Socket\Common\CommandList;
  7. use Core\Component\Socket\Response;
  8. use Core\Swoole\AsyncTaskManager;
  9. use Core\Swoole\Server;
  10. class Register extends AbstractCommandRegister
  11. {
  12. function register(CommandList $commandList)
  13. {
  14. // TODO: Implement register() method.
  15. $commandList->addCommandHandler('hello',function (Command $request,TcpClient $client){
  16. $message = $request->getMessage();
  17. Logger::getInstance()->console('message is '.$message,false);
  18. AsyncTaskManager::getInstance()->add(function ()use($client){
  19. sleep(2);
  20. Response::response($client,"this is delay message for hello\n");
  21. });
  22. return "response for hello\n";
  23. });
  24. $commandList->addCommandHandler('close',function (Command $request,TcpClient $client){
  25. Response::response($client,"you are going to disconnect\n");
  26. Server::getInstance()->getServer()->close($client->getFd(),$client->getReactorId());
  27. });
  28. $commandList->setDefaultHandler(function (){
  29. return "unkown command\n";
  30. });
  31. }
  32. }

添加事件监听

在EasySwoole的启动前事件中:

  1. use App\Sock\Parser;
  2. use App\Sock\Register;
  3. use Core\Component\Socket\Dispatcher;
  4. function beforeWorkerStart(\swoole_server $server){
  5. $listener = $server->addlistener('0.0.0.0',9502,SWOOLE_TCP);
  6. $listener->set(array(
  7. "open_eof_check"=>false,
  8. "package_max_length"=>2048,
  9. ));
  10. $listener->on("receive",function(\swoole_server $server,$fd,$from_id,$data){
  11. Dispatcher::getInstance(Register::class,Parser::class)->dispatchTCP($fd,$from_id,$data);
  12. });
  13. }

测试

启动EasySwoole,执行:

  1. telnet 127.0.0.1 9501

分别输入:

  • hello
  • hello,message
  • abc,
  • close

观察结果。