不能。Workerman 本身不内置 MQTT 协议栈,需借助官方扩展 workerman/mqtt 实现,该扩展基于 Workerman 构建,支持 MQTT v3.1.1,提供 Server 类并需显式调用 listen() 启动监听。

Workerman 能不能直接跑 MQTT 服务?
不能。Workerman 本身不内置 MQTT 协议栈,也没有 MQTTServer 类。它只提供 TCP/UDP/WebSocket 底层通信能力,MQTT 是应用层协议,必须自己解析或借助第三方库。
常见错误现象:Connection refused 或客户端连上就断,往往是因为误以为启动了 MQTT 服务,实际只是开了个裸 TCP 端口。
正确做法是:用 Workerman 搭建一个自定义的 Worker,监听 TCP 端口,再在 onMessage 里手动处理 MQTT 的 CONNECT、PUBLISH、SUBSCRIBE 等报文——但这极容易出错,不推荐从零写。
推荐方案:用 workerman/mqtt 扩展包
workerman/mqtt 是官方维护的轻量 MQTT 服务端实现,基于 Workerman 构建,支持 MQTT v3.1.1,能直接响应标准客户端(如 MQTTX、mosquitto_sub)。
安装方式:
composer require workerman/mqtt
关键点:
-
MQTT\Server是核心类,不是Worker子类,但内部依赖 Workerman 启动 - 必须显式调用
$server->listen(),否则不会真正监听端口 - 默认不启用 TLS,若需
ssl://连接,得额外配置context参数并监听 8883 - 订阅关系由内存管理,重启即丢失;如需持久化,得自己对接 Redis 或数据库
怎么写一个可运行的 MQTT 服务端?
最小可用示例(保存为 mqtt_server.php):
use Workerman\MQTT\Server;
$server = new Server('0.0.0.0', 1883);
$server->onConnect = function ($connection) {
echo "Client connected: {$connection->getRemoteIp()}\n";
};
$server->onSubscribe = function ($connection, $topics) {
echo "Client subscribed to: " . implode(', ', array_keys($topics)) . "\n";
};
$server->onPublish = function ($connection, $topic, $payload, $qos) {
echo "Received on {$topic}: {$payload} (QoS={$qos})\n";
// 可在此做转发、存库、触发业务逻辑
};
$server->listen();
运行命令:
php mqtt_server.php start -d
注意:
- 别漏掉
-d,否则进程前台运行,关终端就停 - 如果本地测试,
mosquitto_pub -h 127.0.0.1 -p 1883 -t 'test' -m 'hello'可验证通路 -
onPublish回调里不能阻塞太久,否则影响并发;重逻辑建议投递到 TaskWorker
为什么消息收不到?几个高频坑
不是代码写错,而是协议细节没对齐:
- 客户端用 MQTT v5 连接 v3.1.1 服务端会静默断开,
workerman/mqtt当前不支持 v5 - 主题(topic)区分大小写,
sensor/temp和SENSOR/TEMP是两个不同主题 - QoS=1/2 的消息,客户端未正确回复 PUBACK/PUBREC,服务端会反复重发,导致连接异常中断
- Workerman 主进程被 kill 后,子进程可能残留,用
ps aux | grep mqtt_server清理干净再重启
最常被忽略的一点:MQTT 的「遗嘱消息(Will Message)」和「Clean Session」标志位,会影响客户端重连时的订阅恢复行为——这和 Workerman 无关,但调试时若没意识到,会误判为服务端问题。










