Expo + TypeScript连接MQTT Broker异常问题求助
解决方案
核心问题分析
Node.js 环境支持原生 TCP 套接字,但 Expo/React Native 的 JavaScript 运行时(Hermes/JSC)在移动端无法直接使用裸 TCP 连接 MQTT Broker,必须通过 WebSocket 协议(ws:///wss://)通信。这也是你在 Node 里能正常连接、Expo 里却连接关闭的根本原因。
针对 mqtt 包的修复方案
1. 替换连接协议与端口
将原 mqtt:// 协议改为 ws://(非加密)或 wss://(加密),对应 Broker 的 WebSocket 端口:
- 常见 Broker 默认端口:EMQX(ws:8083、wss:8084)、Mosquitto(需手动开启 WebSocket 监听)
- 本地测试时,不要用
localhost,改用电脑的局域网 IP(比如192.168.1.100),因为 Expo Go 里的localhost指向设备本身而非开发电脑。
2. 调整客户端配置 + 清理资源
在 useEffect 中添加必要配置,并在组件卸载时关闭连接避免内存泄漏:
import React, { useEffect } from 'react'; import { View, Text } from 'react-native'; import mqtt from 'mqtt'; export default function MqttTest() { useEffect(() => { // 用局域网IP+WebSocket端口连接,末尾的/mqtt部分部分Broker需要(比如EMQX) const client = mqtt.connect('ws://192.168.1.100:8083/mqtt', { clientId: `expo-client-${Math.random().toString(16).slice(2)}`, // 确保客户端ID唯一 clean: true, connectTimeout: 30000, reconnectPeriod: 1000, }); client.on('connect', () => { console.log('Connected to MQTT broker'); client.subscribe('test/topic', (err) => { if (!err) client.publish('test/topic', 'Hello from Expo'); }); }); client.on('close', () => console.log('Connection to MQTT broker closed')); client.on('error', (err) => console.error('MQTT error:', err)); // 组件卸载时关闭连接 return () => client.end(); }, []); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>MQTT Connection Test</Text> </View> ); }
3. 配置 Broker 开启 WebSocket 监听
以 Mosquitto 为例,修改配置文件添加:
listener 8083 protocol websockets
保存后重启 Broker 服务。
其他库问题说明
1. react-native-mqtt 报错
该库依赖原生模块,Expo Managed Workflow 无法直接使用(需 eject 到 Bare Workflow),且版本陈旧兼容性差,不推荐在 Expo 项目中使用。
2. paho-mqtt 连接关闭
同样是协议/地址问题,需改用 WebSocket 端口,以下是修正后的示例代码:
import React, { useEffect } from 'react'; import { View, Text } from 'react-native'; import Paho from 'paho-mqtt'; export default function PahoMqttTest() { useEffect(() => { const client = new Paho.Client( '192.168.1.100', 8083, '/mqtt', `expo-paho-client-${Math.random().toString(16).slice(2)}` ); client.onConnectionLost = (res) => { if (res.errorCode !== 0) console.log('Connection lost:', res.errorMessage); }; client.onMessageArrived = (msg) => console.log('Received:', msg.payloadString); client.connect({ onSuccess: () => { console.log('Connected via Paho'); client.subscribe('test/topic'); const msg = new Paho.Message('Hello from Expo Paho'); msg.destinationName = 'test/topic'; client.send(msg); }, onFailure: (err) => console.error('Paho connect failed:', err), connectTimeout: 30000, }); return () => client.disconnect(); }, []); return <View><Text>Paho MQTT Test</Text></View>; }
额外注意事项
- iOS 端如果使用非加密的
ws://,需在app.json中添加 ATS 例外配置:
生产环境建议改用加密的"ios": { "infoPlist": { "NSAppTransportSecurity": { "NSAllowsArbitraryLoads": true } } }wss://避免配置 ATS。 - 确保 Broker 所在网络允许设备访问(无防火墙/端口限制)。
内容的提问来源于stack exchange,提问作者null_voyager
相关产品推荐
相关产品推荐

