许多 PHP 中的 MQTT ClientBuilder

huangapple go评论59阅读模式
英文:

Many mqtt ClientBuilder in Php

问题

我想在PHP中拥有多个ClientBuilders,并让它们同时运行。目前,我可以创建一个,但当我添加一个新的时候,这部分代码:

$mqtt->loop(true);

会阻止新的ClientBuilder的执行。

目前,我使用ClientBuilder并按以下方式进行操作:

$connectionSettings = (new \PhpMqtt\Client\ConnectionSettings)
    ->setUsername("username")
    ->setPassword("passwd")
    ->setConnectTimeout(3)
    ->setUseTls(false);
$connectionSettings2 = (new \PhpMqtt\Client\ConnectionSettings)
    ->setUsername("username2")
    ->setPassword("passw2")
    ->setConnectTimeout(3)
    ->setUseTls(false);
$mqtt = ClientBuilder::create();
$mqtt2 = ClientBuilder::create();

try {
    $mqtt->connect($connectionSettings, true);
    $mqtt2->connect($connectionSettings2, true);
} catch (\Exception $e) {
    $io->error(__('Error to connect {0}', $e->getMessage()));
}
$filter = 'filter01';
$filter2 = 'filter02';
$idStartAt = strlen($filter) - 1;
$idStartAt2 = strlen($filter2) - 1;
$mqtt->subscribe($filter, function ($topic, $message) use ($idStartAt, $io) {
    $this->fct($topic, $idStartAt, $message, $io);
}, 0);
$mqtt2->subscribe($filter2, function ($topic, $message) use ($idStartAt2, $io) {
    $this->fct2($topic, $idStartAt2, $message, $io);
}, 0);

$mqtt->loop(true);
$mqtt2->loop(true);

$mqtt->disconnect();
$mqtt2->disconnect();

我该怎么做?

英文:

I would like to have several ClientBuilders in php and have them all run at the same time. At the moment I can create one but when I add a new one, the part :

$mqtt->loop(true)

blocks the execution of the new ClientBuilder.

At the moment I use the ClientBuilder and I proceed in the following way:

$connectionSettings = (new \PhpMqtt\Client\ConnectionSettings)
     ->setUsername("username")
     ->setPassword("passwd")
     ->setConnectTimeout(3)
     ->setUseTls(false);
$connectionSettings2 = (new \PhpMqtt\Client\ConnectionSettings)
     ->setUsername("username2")
     ->setPassword("passw2")
     ->setConnectTimeout(3)
     ->setUseTls(false);
$mqtt = ClientBuilder::create();
$mqtt2 = ClientBuilder::create();

try {
   $mqtt->connect($connectionSettings, true);
   $mqtt2->connect($connectionSettings2, true);
} catch (\Exception $e) {
   $io->error(__('Error to connect {0}', $e->getMessage()));
}
$filter = 'filter01';
$filter2 = 'filter02';
$idStartAt = strlen($filter) - 1;
$idStartAt2 = strlen($filter2) - 1;
$mqtt->subscribe($filter, function ($topic, $message) use ($idStartAt, $io) {
   $this->fct($topic, $idStartAt, $message, $io);
}, 0);
$mqtt2->subscribe($filter2, function ($topic, $message) use ($idStartAt2, $io) {
   $this->fct2($topic, $idStartAt2, $message, $io);
}, 0);

$mqtt->loop(true);
$mqtt2->loop(true);

$mqtt->disconnect();
$mqtt2->disconnect();

What can I do?

答案1

得分: 1

正如你所发现的,loop(true) 会一直阻塞,而 $mqtt->loop(true) 后的代码只有在循环退出后才会执行。loop() 方法(带有你的参数)实际上等同于:

$loopStartedAt = microtime(true);
while (true) {
    $this->loopOnce($loopStartedAt, true);
}

loopOnce() 的文档中说:

> 运行一个事件循环迭代,处理来自服务器的消息,并调用已注册的发布消息的回调。还会重发挂起的消息并调用循环事件处理程序。这个方法可以用于在另一个事件循环中集成 MQTT 客户端(比如 ReactPHP 或 Ratchet)。
> 注意:为了确保此方法调用的事件处理程序将收到正确的经过时间,调用方需要提供由 microtime(true) 返回的循环的正确开始时间。

因此,你可以用以下代码替代:

$loopStartedAt = microtime(true);
while (true) {
    $mqtt->loopOnce($loopStartedAt, false);
    $mqtt2->loopOnce($loopStartedAt, false);
    usleep(100000);
}

你可能希望添加一个退出条件(查看 loop() 源代码以了解如何可能工作)。

注意:我没有测试这段代码。
注意2:对于同一代理的多个连接可能不是最佳解决方案(但由于你没有描述你的目标,很难进一步评论)。

英文:

As you have discovered, loop(true) blocks forever and code after $mqtt->loop(true) will not run until the loop exits. The loop() method (with your parameters) is effectively:

$loopStartedAt = microtime(true);
while (true) {
    $this->loopOnce($loopStartedAt, true);
}

The docs for loopOnce() say:

> Runs an event loop iteration that handles messages from the server and calls the registered callbacks for published messages. Also resends pending messages and calls loop event handlers. This method can be used to integrate the MQTT client in another event loop (like ReactPHP or Ratchet).
> Note: To ensure the event handlers called by this method will receive the correct elapsed time, the caller is responsible to provide the correct starting time of the loop as returned by microtime(true).

So you should be able to replace

$mqtt->loop(true);
$mqtt2->loop(true);

with something like:

$loopStartedAt = microtime(true);
while (true) {
    $mqtt->loopOnce($loopStartedAt, false);
    $mqtt2->loopOnce($loopStartedAt, false);
    usleep(100000);
}

You probably want to add an exit condition (see the source for loop() for an example of how this might work).

Note: I have not tested this code.
Note2: Multiple connections to the same broker might not be the best solution (but you have not described your aim so it's difficulty to comment further).

huangapple
  • 本文由 发表于 2023年2月27日 05:28:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75575122.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定