插件窝 干货文章 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 运行 806    来源:    2025-03-13

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

问题分析

simps/mqtt 是一个基于 Swoole 的 MQTT 客户端库,它依赖于 Swoole 的异步 I/O 功能。Swoole 的异步 I/O 功能只能在 CLI 模式下运行,因为 Web 模式下(如通过 Apache 或 Nginx 运行的 PHP)不支持 Swoole 的异步 I/O。

解决方案

要解决这个问题,你可以采取以下几种方法:

1. 在 CLI 模式下运行

将你的 MQTT 客户端代码放在一个独立的 PHP 脚本中,并通过命令行运行它。例如:

// mqtt_client.php
require 'vendor/autoload.php';

use Simps\MQTT\Client;

$client = new Client('your-mqtt-broker-url', 1883);
$client->connect();

// 订阅主题
$client->subscribe('your/topic');

// 发布消息
$client->publish('your/topic', 'Hello, MQTT');

// 保持连接
while (true) {
    $client->loop();
}

然后在命令行中运行:

php mqtt_client.php

2. 使用同步模式

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

require 'vendor/autoload.php';

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

$server   = 'your-mqtt-broker-url';
$port     = 1883;
$clientId = 'your-client-id';

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

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

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

// 订阅主题
$mqtt->subscribe('your/topic', function ($topic, $message) {
    echo sprintf("Received message on topic [%s]: %s\n", $topic, $message);
}, 0);

// 发布消息
$mqtt->publish('your/topic', 'Hello, MQTT', 0);

// 保持连接
$mqtt->loop(true);

3. 使用 WebSocket 或其他协议

如果你需要在 Web 模式下与 MQTT 服务器通信,可以考虑使用 WebSocket 或其他协议来连接 MQTT 服务器。阿里云物联网平台支持 WebSocket 协议,你可以使用 WebSocket 客户端库来连接。

总结

  • 如果你需要在 CLI 模式下运行 MQTT 客户端,可以使用 simps/mqtt 并在命令行中运行脚本。
  • 如果你需要在 Web 模式下运行 MQTT 客户端,建议使用支持同步模式的 MQTT 客户端库,或者考虑使用 WebSocket 协议。

根据你的具体需求选择合适的解决方案。