uniapp,微信小程序中使用 MQTT的問題
最近在uniapp打包成微信小程序的項(xiàng)目中第一次用到了MQTT。使用比較簡(jiǎn)單,但是還是遇到了一些問題。在此記錄一下。
官方文檔:MQTT Github
官方MQTT測(cè)試工具:MQTTX。測(cè)試工具使用說明
MQTT的js文件:mqtt.min.js
先上一點(diǎn)注意事項(xiàng):
(1)MQTT.js 一個(gè) MQTT 協(xié)議的客戶端庫(kù),用 JavaScript 編寫,可用于 Node.js 和瀏覽器。在 Node.js 端可以通過全局安裝使用命令行連接,同時(shí)還支持 MQTT ,MQTT TLS 證書連接;值得一提的是 MQTT.js 還對(duì)微信小程序有較好的支持。
(2)MQTT可以通過三種方式連接,TCP直連, TLS和WebSocket,但是JavaScript使用 TCP 只能通過 ws 即 Websocket 鏈接。所以如果服務(wù)器是TCP直連,客戶端是肯定連不上的,會(huì)報(bào) Error in connection establishment 的錯(cuò)誤。所以客戶端協(xié)議只能是ws,wss,wxs(微信)
(3)WebSocket 是一種在單個(gè) TCP 連接上進(jìn)行全雙工通訊的協(xié)議。作為一種通信協(xié)議,其使用 ws(非加密)、wss(SSL 加密) 作為協(xié)議標(biāo)識(shí)。MQTT.js 客戶端支持多種協(xié)議,連接地址需指明協(xié)議類型;
(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') // 這是為了給自己發(fā)條消息,其它無作用 client.subscribe('test', (err) => { if (!err) { client.publish('test', '{}') } }) }); // 自動(dòng)重連 client.on('reconnect', (msg) => { console.log('reconnect', msg) }); // 錯(cuò)誤 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) => { // 把a(bǔ)rrayBuffer轉(zhuǎn)成字符串 let encodedString = String.fromCharCode.apply(null, new Uint8Array(message));// 全局發(fā)送消息 uni.$emit('sendTopicMsg',encodedString); console.log(encodedString) }) // 全局監(jiān)聽是否有關(guān)閉mqtt的消息的事件 uni.$on('closeMqtt',() => { client.end(true); // 主動(dòng)斷開連接 })
說明:
(1) 配置項(xiàng)里的 keepAlive 指的是心跳時(shí)間。以秒為單位。定義服務(wù)端從客戶端接收到消息的最大間隔時(shí)間??梢栽O(shè)置為0,表示客戶端一直不斷開,除非主動(dòng)斷開。
(2) clean 設(shè)置為false,是為了讓客戶端掉線的時(shí)候,服務(wù)器必須在客戶端斷開之后繼續(xù)存儲(chǔ)/保持客戶端的訂閱狀態(tài)。即當(dāng)為true的時(shí)候,如果掉線了,服務(wù)端會(huì)清理鏈接狀態(tài)的數(shù)據(jù)和內(nèi)容。當(dāng)為false的時(shí)候,服務(wù)端會(huì)保存消息發(fā)送期間,鏈接斷開導(dǎo)致發(fā)送失敗的消息。這樣連上的時(shí)候就會(huì)自動(dòng)推送到訂閱的客戶端。
(3) 如果連接需要驗(yàn)證用戶名和密碼,則需要加上username和password字段。
(4) 微信小程序使用的協(xié)議,如果不是加密的,則是 wss,如果是加密的,就是 wxs。web端,一般不加密就是 wx,加密就是wss。
(5) 前端收到的消息是 arrayBuffer 格式的,需要轉(zhuǎn)成字符串格式,如果帶有中文,可能轉(zhuǎn)成字符串會(huì)亂碼??梢允褂胠et decodeString = decodeURIComponent(escape((encodedString))) 來避免中文亂碼?;蛘呤蔷W(wǎng)上通過移位轉(zhuǎn)成中文的方法來解決。
(6) clientId 是使用Math.random().toString(36).substr(3,自定義長(zhǎng)度) 來生成自定義長(zhǎng)度的的唯一id。
應(yīng)該是免費(fèi)的測(cè)試MQTT消息的鏈接:o(∩_∩)o
協(xié)議 | 地址 | 端口 | 路徑 | 證書 |
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 這個(gè)直接在MQTTX測(cè)試工具里面 選擇 SSL/TLS 勾選為true時(shí)即可選擇。
(2) 測(cè)試的時(shí)候,先填好內(nèi)容,然后鏈接上的時(shí)候,再添加一個(gè)訂閱,Topic就填一會(huì)你需要發(fā)送消息的Topic,這樣當(dāng)你模擬服務(wù)器發(fā)送消息的時(shí)候,MQTTX里面也會(huì)收到你剛才發(fā)送的內(nèi)容,這樣就是連通了。
開發(fā)過程中遇到的問題:
(1)如果出現(xiàn)failed: Connection closed before receiving a handshake response這個(gè)錯(cuò)誤。說明 服務(wù)端的 mqtt 協(xié)議和客戶端的協(xié)議不一樣,就比如python用的是基于 tcp 的 mqtt ,js是基于websocket 的 mqtt,都不能達(dá)成握手的操作。出現(xiàn)這個(gè)的問題應(yīng)該是:服務(wù)端使用了1883這個(gè)端口,而客戶端也是用這個(gè)端口,就導(dǎo)致這個(gè)問題。正確的應(yīng)該是:客戶端(js)應(yīng)該使用8083端口(未加密)。
(2) 最初我設(shè)置心跳時(shí)間是3秒,在微信開發(fā)者工具,或者H5端的時(shí)候,是沒有問題的。但是在小程序真機(jī)調(diào)試?yán)?,?dāng)小程序切換到后臺(tái),差不多5s就會(huì)自動(dòng)斷開,然后一直重連,直到切換回小程序,重連成功。而且有時(shí)候還會(huì)連續(xù)斷開和重連。自動(dòng)斷網(wǎng)這個(gè)原因,小程序官網(wǎng)做了說明的:超過5s斷網(wǎng)說明在第二條 網(wǎng)絡(luò)請(qǐng)求 - 使用限制里面就說明了,小程序的機(jī)制,限制了切換到后臺(tái)之后網(wǎng)絡(luò)的處理。所以把心跳時(shí)間改為30s,讓 mqtt 30秒之后再自動(dòng)重連。但是這樣只是為了讓體驗(yàn)稍微好一點(diǎn),不會(huì)出現(xiàn)切換出去5s就斷開鏈接,再切回來一直提示重連的問題。不過可以把心跳時(shí)間改為0,表示一直連接不斷開。
總結(jié):
(1)以上對(duì)mqtt的了解也只是一知半解,還沒弄明白這里的心跳時(shí)間,和 TCP/IP 的心跳機(jī)制是不是一樣的。超過心跳時(shí)間,能不能讓客戶端不掉線,或者有沒有更好的解決離線的辦法。
(2)而且還有很多特性都沒用到,比如will遺愿標(biāo)志,專門用來處理客戶端斷開連接的配置項(xiàng)。
(3)由于這個(gè)項(xiàng)目都是用的Qos0的消息,都不知道與Qos1,Qos2的區(qū)別是什么。
到此這篇關(guān)于uniapp,微信小程序中使用 MQTT的文章就介紹到這了,更多相關(guān)微信小程序MQTT內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript跨域請(qǐng)求包裝函數(shù)與用法示例
這篇文章主要介紹了javascript跨域請(qǐng)求包裝函數(shù)與用法,結(jié)合實(shí)例形式分析了javascript基于ajax的跨域請(qǐng)求封裝函數(shù)與相關(guān)使用技巧,需要的朋友可以參考下2016-11-11javascript函數(shù)的call、apply和bind的原理及作用詳解
javascript函數(shù)的call、apply和bind?本質(zhì)是用來實(shí)現(xiàn)繼承的,專業(yè)點(diǎn)說法就是改變函數(shù)體內(nèi)部this的指向,當(dāng)一個(gè)對(duì)象沒有某個(gè)功能時(shí),就可以用這3個(gè)來從有相關(guān)功能的對(duì)象里借用過來,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05深入理解JavaScript系列(34):設(shè)計(jì)模式之命令模式詳解
這篇文章主要介紹了深入理解JavaScript系列(34):設(shè)計(jì)模式之命令模式詳解,命令模式(Command)的定義是:用于將一個(gè)請(qǐng)求封裝成一個(gè)對(duì)象,從而使你可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化,對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志,以及執(zhí)行可撤銷的操作,需要的朋友可以參考下2015-03-03《JavaScript DOM 編程藝術(shù)》讀書筆記之DOM基礎(chǔ)
這篇文章主要介紹了《JavaScript DOM 編程藝術(shù)》讀書筆記之DOM基礎(chǔ),需要的朋友可以參考下2015-01-01原生js的數(shù)組除重復(fù)簡(jiǎn)單實(shí)例
下面小編就為大家?guī)硪黄鷍s的數(shù)組除重復(fù)簡(jiǎn)單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-05-05關(guān)于var在for循環(huán)遇到的問題解決
這篇文章主要給大家介紹了關(guān)于var在for循環(huán)遇到的問題的幾種解決方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-07-07前端項(xiàng)目npm?install?安裝依賴報(bào)錯(cuò)的解決方案(三種問題解決方案)
本文給大家介紹前端項(xiàng)目npm?install?安裝依賴報(bào)錯(cuò)的解決方案(三種問題解決方案),給大家總結(jié)了前端項(xiàng)目安裝依賴,遇到過的問題,每一種問題給大家完美解決方案,感興趣的朋友一起看看吧2023-12-12