在Node.js下運用MQTT協議實現即時通信及離線推送

前言

前些日子瞭解到mqtt這樣一個協議,能夠在web上達到即時通信的效果,但網上並不能很方便地找到一篇目前版本的在node下正確實現這個協議的博客。html

本身搗鼓了一段時間,理解不深入,但也算是基本可以達到使用目的。node

本文目的爲對MQTT有需求的學習者提供必定程度上的便利,省去了查閱官方文檔及源碼的功夫,但還沒有對離線消息的接收順序進行處理。web

代碼

服務端: server.jsmongodb

//服務端引入中間件mosca
let mosca = require('mosca')
let settings = {
  port: 5112
}
let server = new mosca.Server(settings)
server.on('ready', function(){
    console.log('Mosca server is up and running at port 5112');  
})
server.on('published', function(packet, client) {
  console.log('Published', packet.payload)
})

server.on('clientDisconnected', function(client){
  console.log('disconnected: ', client.id)
})

推送端: pub.js數據庫

//客戶端引入mqtt
let mqtt = require('mqtt');

let client = mqtt.connect('mqtt://localhost', {
  port: 5112,
  clientId: 'cli_pub',
})

let num = 0;
setInterval(function (){
  client.publish('test', 
  'Hello mqtt ' + (++num),
  {qos:1},
  () => console.log(num));
}, 1000)

訂閱端: sub.jsnpm

let mqtt = require('mqtt')

let client = mqtt.connect('mqtt://localhost', {
  port: 5112,
  clientId: 'cli_sub',
})

client.subscribe('test',{qos:1})

client.on('message', function (topic, message) {
  console.log('received message: ', message.toString())
})

server運行後,先啓動sub,再啓動pub,便可在sub中接收到推送過來的消息序列
至此實現了簡單的即時推送json

離線推送相關配置及簡要介紹

離線配置-服務端:

要實現消息的離線推送,必然須要一個存儲臨時數據的部件
此處用到的是mongo,固然能夠根據須要選擇其餘的存儲工具windows

server.js中的settings需更改成:session

let settings = {
  port: 5112,
  persistence:{    //增長了此項
    factory: mosca.persistence.Mongo,
    url: "mongodb://localhost:27017/mosca"
  }
}

factory: 引入mosca對特定存儲工具的一些處理方法
url: 其中的 27017 爲mongo所監聽的端口號,mosca爲存儲相關數據的數據庫函數

值得一提的是:配置好mongo的環境後,不須要提早在mongo中手動建立,若數據庫不存在會自動生成,並且mosca會爲你做好其餘一切基本事項 (即:若只想臨時體驗下效果,甚至能夠暫時把mongo放一邊 )

在mongo中,能夠看到自動新添了db: mosca
及其下的collection(至關於關係型數據庫中的表/關係)

clipboard.png

離線配置-客戶端:

pub.js和sub.js中的client中均可以改成:

let client = mqtt.connect('mqtt://localhost', {
  port: 5112,
  clientId: 'cli_**',
  clean: false//增長了此項
})

clientId: 區分客戶端的識別碼
clean: 此處決定了客戶端在服務端的session是否會被清除,默認爲true,爲實現離線推送,咱們須要將其保留
clean及上文中的persistence爲實現離線推送的關鍵配置

mqtt.connect()會返回一個mqttClient對象,包含了:reconnect(), subscribe(), publish()等一系列方法。

本文中發送端接收端被分爲了pub.js和sub.js兩個獨立文件,僅僅爲了方便在不一樣控制檯中觀察效果
一個client能夠既爲推送端,又爲訂閱端


至此,全部代碼已完成

其餘介紹:

client.subscribe():
爲本客戶端訂閱一個話題,全部訂閱此話題的用戶都會收到在此話題下推送的信息

//client.subscribe(topic,opts)
client.subscribe('test',{qos:1})

opts中的qos爲通訊機制,控制發送端與接收端的互鎖程度
上文中的其中一個collection: subscriptions即記錄各用戶話題訂閱狀況

用戶cli_sub及cli2_sub訂閱了話題test:
clipboard.png
(新增一個cli2_pub,下文有用)

注:
重複執行腳本sub.js實際上對topic進行了重複訂閱
實際編碼時,應避免topic的重複訂閱,即便重複訂閱並不影響實現效果

client.publish():
向指定topic發送數據
message爲Buffer或String格式,能夠經過序列化或轉json實現對複雜數據對象的傳送

//client.publish(topic, message, opts, callback)
let num = 0;
setInterval(function (){
  client.publish('test', 
  'Hello mqtt ' + (++num),
  {qos:1},
  () => console.log(num));
}, 1000)

參數再也不贅述
此處用一個定時器定時在 topic: test 下發送'Hello mqtt 1,2,3..'

用回調函數實時打印一下發送的num:
clipboard.png

當訂閱者處於離線狀態時,能夠在collection: packets中查看到臨時數據的存儲狀況:
clipboard.png
mosca把每一條推送消息爲全部訂閱用戶都生成了獨立的記錄,用同一個messageId進行關聯

當其中一個用戶(cli2_sub)上線時,獲取到其對應的數據,
clipboard.png
然後數據庫中相應記錄便會被刪除
clipboard.png
此時僅有cli_sub用戶的數據
當cli2_sub上線接收消息後,packets中記錄將被清空

client.on():
即在client上觸發的事件,此處只列舉消息接收事件

//client.on(event, callback)
client.on('message', function (topic, message) {
  console.log('received message: ', message.toString())
})

處理爲簡單地打印到控制檯

mosca.js文檔:
https://www.npmjs.com/package...
mqtt.js文檔:
https://www.npmjs.com/package...
windows環境下mongo的配置:
https://jingyan.baidu.com/art...
及一位前輩的文章:
https://www.jianshu.com/p/831...

轉載請註明出處 ; )

相關文章
相關標籤/搜索