uniapp,微信小程序中使用 MQTT的问题


Posted in Javascript onJuly 11, 2020

最近在uniapp打包成微信小程序的项目中第一次用到了MQTT。使用比较简单,但是还是遇到了一些问题。在此记录一下。

官方文档:MQTT Github

官方MQTT测试工具:MQTTX。测试工具使用说明

MQTT的js文件:mqtt.min.js

先上一点注意事项:

(1)MQTT.js 一个 MQTT 协议的客户端库,用 JavaScript 编写,可用于 Node.js 和浏览器。在 Node.js 端可以通过全局安装使用命令行连接,同时还支持 MQTT ,MQTT TLS 证书连接;值得一提的是 MQTT.js 还对微信小程序有较好的支持。

(2)MQTT可以通过三种方式连接,TCP直连, TLS和WebSocket,但是JavaScript使用 TCP 只能通过 ws 即 Websocket 链接。所以如果服务器是TCP直连,客户端是肯定连不上的,会报 Error in connection establishment 的错误。所以客户端协议只能是ws,wss,wxs(微信)

(3)WebSocket 是一种在单个 TCP 连接上进行全双工通讯的协议。作为一种通信协议,其使用 ws(非加密)、wss(SSL 加密) 作为协议标识。MQTT.js 客户端支持多种协议,连接地址需指明协议类型;

(4)ws: 未加密的 WebSocket 连接,一般使用8083端口。wss: 加密的 WebSocket 连接,一般使用8084端口。mqtt: 未加密的 TCP 连接,一般使用1883端口。mqtts: 加密 TCP 连接。

贴一下代码:

import $mqtt from './mqtt.min.js';

const mqttOptions = {
  keepalive: 30,
  clean: false, 
  connectTimeout: 5000, // Timeout
  clientId: uni.getStorageSync('clientId'),
  // username: 'test',
  // password: 'test',
}

const connectUrl = `${mqttHost}:${mqttPort}/mqtt`;

// #ifdef H5
var client = $mqtt.connect('wss://' + connectUrl, mqttOptions);
// #endif

// #ifdef MP-WEIXIN||APP-PLUS
var client = $mqtt.connect('wxs://' + connectUrl, mqttOptions);
// #endif

client.on('connect', () => {
  console.log('connect')
// 这是为了给自己发条消息,其它无作用
  client.subscribe('test', (err) => {
    if (!err) {
      client.publish('test', '{}')
    }
  })
});
// 自动重连
client.on('reconnect', (msg) => {
  console.log('reconnect', msg)
});
// 错误
client.on('error', () => {
  console.log('error')
});
// 断开
client.on('end', () => {
  console.log('end')
});
// 掉线
client.on('offline', (msg) => {
  console.log('offline',msg)
});
// 收到消息    
client.on('message', (topic, message) => {
  // 把arrayBuffer转成字符串
  let encodedString = String.fromCharCode.apply(null, new Uint8Array(message));// 全局发送消息
  uni.$emit('sendTopicMsg',encodedString);

 console.log(encodedString)
})

// 全局监听是否有关闭mqtt的消息的事件
uni.$on('closeMqtt',() => {
  client.end(true); // 主动断开连接
})

说明:

(1) 配置项里的 keepAlive 指的是心跳时间。以秒为单位。定义服务端从客户端接收到消息的最大间隔时间。可以设置为0,表示客户端一直不断开,除非主动断开。

(2) clean 设置为false,是为了让客户端掉线的时候,服务器必须在客户端断开之后继续存储/保持客户端的订阅状态。即当为true的时候,如果掉线了,服务端会清理链接状态的数据和内容。当为false的时候,服务端会保存消息发送期间,链接断开导致发送失败的消息。这样连上的时候就会自动推送到订阅的客户端。

(3) 如果连接需要验证用户名和密码,则需要加上username和password字段。

(4) 微信小程序使用的协议,如果不是加密的,则是 wss,如果是加密的,就是 wxs。web端,一般不加密就是 wx,加密就是wss。

(5) 前端收到的消息是 arrayBuffer 格式的,需要转成字符串格式,如果带有中文,可能转成字符串会乱码。可以使用let decodeString = decodeURIComponent(escape((encodedString))) 来避免中文乱码。或者是网上通过移位转成中文的方法来解决。

(6) clientId 是使用Math.random().toString(36).substr(3,自定义长度) 来生成自定义长度的的唯一id。

应该是免费的测试MQTT消息的链接:o(∩_∩)o

协议 地址 端口 路径 证书
mqtt broker.hivemq.com 8000
mqtt broker.emqx.io 1883
ws test.mosquitto.org 8080 /mqtt
wss test.mosquitto.org 8081 /mqtt CA signed server

(1) CA signed server 这个直接在MQTTX测试工具里面 选择 SSL/TLS 勾选为true时即可选择。

(2) 测试的时候,先填好内容,然后链接上的时候,再添加一个订阅,Topic就填一会你需要发送消息的Topic,这样当你模拟服务器发送消息的时候,MQTTX里面也会收到你刚才发送的内容,这样就是连通了。

开发过程中遇到的问题:

(1)如果出现failed: Connection closed before receiving a handshake response这个错误。说明 服务端的 mqtt 协议和客户端的协议不一样,就比如python用的是基于 tcp 的 mqtt ,js是基于websocket 的 mqtt,都不能达成握手的操作。出现这个的问题应该是:服务端使用了1883这个端口,而客户端也是用这个端口,就导致这个问题。正确的应该是:客户端(js)应该使用8083端口(未加密)。

(2) 最初我设置心跳时间是3秒,在微信开发者工具,或者H5端的时候,是没有问题的。但是在小程序真机调试里,当小程序切换到后台,差不多5s就会自动断开,然后一直重连,直到切换回小程序,重连成功。而且有时候还会连续断开和重连。自动断网这个原因,小程序官网做了说明的:超过5s断网说明在第二条 网络请求 - 使用限制里面就说明了,小程序的机制,限制了切换到后台之后网络的处理。所以把心跳时间改为30s,让 mqtt 30秒之后再自动重连。但是这样只是为了让体验稍微好一点,不会出现切换出去5s就断开链接,再切回来一直提示重连的问题。不过可以把心跳时间改为0,表示一直连接不断开。

总结:

(1)以上对mqtt的了解也只是一知半解,还没弄明白这里的心跳时间,和 TCP/IP 的心跳机制是不是一样的。超过心跳时间,能不能让客户端不掉线,或者有没有更好的解决离线的办法。

(2)而且还有很多特性都没用到,比如will遗愿标志,专门用来处理客户端断开连接的配置项。

(3)由于这个项目都是用的Qos0的消息,都不知道与Qos1,Qos2的区别是什么。

到此这篇关于uniapp,微信小程序中使用 MQTT的文章就介绍到这了,更多相关微信小程序MQTT内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
jQuery Deferred和Promise创建响应式应用程序详细介绍
Mar 05 Javascript
jquery中的on方法使用介绍
Dec 29 Javascript
jquery插件推荐 jquery.cookie
Nov 09 Javascript
javascript继承的六大模式小结
Apr 13 Javascript
Jquery判断radio、selelct、checkbox是否选中及获取选中值方法总结
Apr 15 Javascript
jQuery实现给页面换肤的方法
May 30 Javascript
js实现网页多级级联菜单代码
Aug 20 Javascript
jquery实现全选和全不选功能效果的实现代码【推荐】
May 05 Javascript
详解BootStrap中Affix控件的使用及保持布局的美观的方法
Jul 08 Javascript
详解用原生JavaScript实现jQuery的某些简单功能
Dec 19 Javascript
解决vue移动端适配问题
Dec 12 Javascript
详解wepy开发小程序踩过的坑(小结)
May 22 Javascript
VSCode 配置uni-app的方法
Jul 11 #Javascript
深入解析微信小程序开发中遇到的几个小问题
Jul 11 #Javascript
微信小程序上传帖子的实例代码(含有文字图片的微信验证)
Jul 11 #Javascript
详解JavaScript匿名函数和闭包
Jul 10 #Javascript
Vue watch响应数据实现方法解析
Jul 10 #Javascript
详解Vue之事件处理
Jul 10 #Javascript
jQuery开发仿QQ版音乐播放器
Jul 10 #jQuery
You might like
在 PHP 中使用随机数的三个步骤
2006/10/09 PHP
php使用imagick模块实现图片缩放、裁剪、压缩示例
2014/04/17 PHP
PHP PDO fetch 模式各种参数的输出结果一览
2015/01/07 PHP
PHP关键特性之命名空间实例详解
2017/05/06 PHP
PHP实现广度优先搜索算法(BFS,Broad First Search)详解
2017/09/16 PHP
php中字符串和整数比较的操作方法
2019/06/06 PHP
php基于 swoole 实现的异步处理任务功能示例
2019/08/13 PHP
离开页面时检测表单元素是否被修改,提示保存的js代码
2010/08/25 Javascript
jquery的键盘事件修改代码
2011/02/24 Javascript
js显示时间 js显示最后修改时间
2013/01/02 Javascript
NodeJs安装npm包一直失败的解决方法
2017/04/28 NodeJs
解决React Native端口号修改的方法
2017/07/28 Javascript
深入探讨JavaScript的最基本部分之执行上下文
2019/02/12 Javascript
7个好用的JavaScript技巧分享(译)
2019/05/07 Javascript
解决vue.js提交数组时出现数组下标的问题
2019/11/05 Javascript
[01:10:58]KG vs TNC 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Python文件和流(实例讲解)
2017/09/12 Python
PyTorch读取Cifar数据集并显示图片的实例讲解
2018/07/27 Python
python3实现多线程聊天室
2018/12/12 Python
Python实现Event回调机制的方法
2019/02/13 Python
python整合ffmpeg实现视频文件的批量转换
2019/05/31 Python
Python Pandas 获取列匹配特定值的行的索引问题
2019/07/01 Python
Python实用工具FuckIt.py介绍
2019/07/02 Python
Python 实现opencv所使用的图片格式与 base64 转换
2020/01/09 Python
TensorFLow 不同大小图片的TFrecords存取实例
2020/01/20 Python
python实现电子词典
2020/03/03 Python
详解HTML5 window.postMessage与跨域
2017/05/11 HTML / CSS
俄罗斯马克西多姆家居用品网上商店:Максидом
2020/02/06 全球购物
什么叫做SQL注入,如何防止
2016/10/04 面试题
某公司C#程序员面试题笔试题
2014/05/26 面试题
中学生纪念九一八事变演讲稿
2014/09/14 职场文书
乡镇党的群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
党员教师群众路线思想汇报范文
2014/10/28 职场文书
成本低的5个创业项目:投资小、赚钱快
2019/08/20 职场文书
导游词之苏州盘门景区
2019/11/12 职场文书
分析SQL窗口函数之聚合窗口函数
2022/04/21 Oracle