插件窝 干货文章 ThinkPHP6中使用simps/mqtt连接阿里云物联网平台MQTT报错“async-io must be used in PHP CLI mode”怎么办?

ThinkPHP6中使用simps/mqtt连接阿里云物联网平台MQTT报错“async-io must be used in PHP CLI mode”怎么办?

mqtt Client 使用 模式 136    来源:    2025-03-14

在使用 simps/mqtt 连接阿里云物联网平台时,报错“async-io must be used in PHP CLI mode”通常是因为 simps/mqtt 的异步 I/O 功能只能在 PHP CLI 模式下运行,而不能在 Web 模式下运行。

原因分析

simps/mqtt 使用了 react/event-loopreact/socket 等库来实现异步 I/O 操作。这些库依赖于 PHP 的事件循环,而事件循环通常只能在 CLI 模式下运行,因为在 Web 模式下,PHP 脚本是同步执行的,无法实现异步 I/O。

解决方案

1. 使用 CLI 模式运行

如果你需要在 ThinkPHP6 中使用 simps/mqtt,建议将 MQTT 客户端放在 CLI 模式下运行。你可以创建一个命令行任务来处理 MQTT 的连接和消息处理。

步骤: 1. 在 ThinkPHP6 中创建一个命令行任务。 2. 在命令行任务中初始化 simps/mqtt 客户端并连接到阿里云物联网平台。

示例代码:

namespace app\command;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use Simps\MQTT\Client;

class MqttClient extends Command
{
    protected function configure()
    {
        $this->setName('mqtt:client')->setDescription('MQTT Client');
    }

    protected function execute(Input $input, Output $output)
    {
        $client = new Client([
            'host' => 'your-iot-endpoint',
            'port' => 1883,
            'username' => 'your-device-name',
            'password' => 'your-device-secret',
            'client_id' => 'your-client-id',
        ]);

        $client->onConnect(function () use ($client) {
            echo "Connected\n";
            $client->subscribe('your-topic');
        });

        $client->onMessage(function ($topic, $message) {
            echo "Received message on topic {$topic}: {$message}\n";
        });

        $client->loop();
    }
}

然后在命令行中运行:

php think mqtt:client

2. 使用同步 MQTT 客户端

如果你必须在 Web 模式下使用 MQTT,可以考虑使用同步的 MQTT 客户端库,而不是 simps/mqtt。例如,可以使用 php-mqtt/client 这个库,它支持同步操作。

示例代码:

use PhpMqtt\Client\MqttClient;
use PhpMqtt\Client\ConnectionSettings;

$server   = 'your-iot-endpoint';
$port     = 1883;
$clientId = 'your-client-id';
$username = 'your-device-name';
$password = 'your-device-secret';

$mqtt = new MqttClient($server, $port, $clientId);

$connectionSettings = (new ConnectionSettings)
    ->setUsername($username)
    ->setPassword($password);

$mqtt->connect($connectionSettings, true);

$mqtt->subscribe('your-topic', function ($topic, $message) {
    echo "Received message on topic {$topic}: {$message}\n";
});

$mqtt->loop(true);

3. 使用 WebSocket 或其他协议

如果你无法在 CLI 模式下运行 MQTT 客户端,可以考虑使用 WebSocket 或其他协议与阿里云物联网平台通信。阿里云物联网平台支持多种协议,你可以选择适合你场景的协议。

总结

  • 如果你需要在 ThinkPHP6 中使用 simps/mqtt,建议在 CLI 模式下运行。
  • 如果你必须在 Web 模式下使用 MQTT,可以考虑使用同步的 MQTT 客户端库。
  • 如果以上方案都不适合,可以考虑使用其他协议与阿里云物联网平台通信。