MQTT 怎么在单独一个端口上分别使用 v3.x 和 v5.0 协议解析?

2021-09-15 16:02:26 浏览数 (1)

MQTT 有 3 个常用的协议等级:v3.1、v3.1.1 和 v5.0,那么如何在一个端口上同时处理 3 种协议等级的解析呢?

例如在 1883 端口上,同时处理 v3.1、v3.1.1 和 v5.0 这 3 种协议等级

simps/mqtt 提供了 MQTT 协议解析的能力,这种需求在之前的版本中也是可以实现的,不过比较麻烦,可能需要这样:

代码语言:javascript复制
use SimpsMQTTProtocolV3;
use SimpsMQTTProtocolV5;

$server->on('receive', function (SwooleServer $server, $fd, $from_id, $data) {
    try {
        $data = V3::unpack($data);
    } catch (Throwable $e) {
        try {
            $data = V5::unpack($data);
        } catch (Throwable $e) {
            throw $e;
        }
    }
    var_dump($data);
});

解析两次数据来进行尝试获取,代码不够优雅

那么现在呢,很简单。安装 simps/mqtt 最新版 v1.4.0,增加了一个getLevel的方法

  • 使用 composer 加载 simps/mqtt
代码语言:javascript复制
composer require simps/mqtt
  • 创建一个 Server
代码语言:javascript复制
use SimpsMQTTProtocolTypes;
use SimpsMQTTProtocolV3;
use SimpsMQTTProtocolV5;
use SimpsMQTTToolsUnPackTool;
use SimpsMQTTProtocolProtocolInterface;

$server = new SwooleServer('127.0.0.1', 1883, SWOOLE_BASE);

$server->set(
    [
        'open_mqtt_protocol' => true,
        'worker_num' => 1,
        'package_max_length' => 2 * 1024 * 1024,
    ]
);

$server->on('connect', function ($server, $fd) {
    echo "Client #{$fd}: Connect.n";
});

$server->on('receive', function (SwooleServer $server, $fd, $from_id, $data) {
    $type = UnPackTool::getType($data);
    if ($type === Types::CONNECT) {
        $level = UnPackTool::getLevel($data);
        $class = $level === ProtocolInterface::MQTT_PROTOCOL_LEVEL_5_0 ? V5::class : V3::class;
        $server->fds[$fd] = ['level' => $level, 'class' => $class];
    }
    /** @var ProtocolInterface $unpack */
    $unpack = $server->fds[$fd]['class'];
    var_dump($unpack::unpack($data));
});

$server->on('close', function ($server, $fd) {
    unset($server->fds[$fd]);
    echo "Client #{$fd}: Close.n";
});

$server->start();

这样代码就看起来简单多了,使用getType获取当前包的类型,在connect类型的时候获取使用协议类型是什么,

然后存到$server->fds中,下文就可以从直接取对应的协议解析类来进行处理。

代码语言:javascript复制
$type = UnPackTool::getType($data);
if ($type === Types::CONNECT) {
    $level = UnPackTool::getLevel($data);
    $class = $level === ProtocolInterface::MQTT_PROTOCOL_LEVEL_5_0 ? V5::class : V3::class;
}

五行代码就可以实现这个功能需求~ 如果你被加鸡腿了不要忘了我哦 :)

分享一个讲解 MQTT 协议的 PPT,你可以不限速下载

0 人点赞