在Node.js下运用MQTT协议实现即时通讯及离线推送的方法


Posted in Javascript onJanuary 24, 2019

前言

前些日子了解到mqtt这样一个协议,可以在web上达到即时通讯的效果,但网上并不能很方便地找到一篇目前版本的在node下正确实现这个协议的博客。

自己捣鼓了一段时间,理解不深刻,但也算是基本能够达到使用目的。

本文尚未对离线消息的接收顺序进行处理。

代码

服务端: server.js

//服务端引入中间件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.js

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运行后,先启动pub,再启动sub,即可在sub中接收到推送过来的消息序列

至此实现了简单的即时推送

离线推送相关配置及简要介绍

离线配置-服务端:

要实现消息的离线推送,必然需要一个存储临时数据的部件

此处用到的是mongo,当然可以根据需要选择其他的存储工具

server.js中的settings需更改为:

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(相当于关系型数据库中的表/关系)

在Node.js下运用MQTT协议实现即时通讯及离线推送的方法

离线配置-客户端:

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:

在Node.js下运用MQTT协议实现即时通讯及离线推送的方法

(新增一个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:

在Node.js下运用MQTT协议实现即时通讯及离线推送的方法

当订阅者处于离线状态时,可以在collection: packets中查看到临时数据的存储情况:

在Node.js下运用MQTT协议实现即时通讯及离线推送的方法

mosca把每一条推送消息为所有订阅用户都生成了独立的记录,用同一个messageId进行关联

当其中一个用户(cli2_sub)上线时,获取到其对应的数据,

在Node.js下运用MQTT协议实现即时通讯及离线推送的方法

而后数据库中相应记录便会被删除

在Node.js下运用MQTT协议实现即时通讯及离线推送的方法

此时仅有cli_sub用户的数据

当cli2_sub上线接收消息后,packets中记录将被清空

client.on():

即在client上触发的事件,此处只列举消息接收事件

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

处理为简单地打印到控制台

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript获得服务器端控件的ID的实现代码
Dec 28 Javascript
分享精心挑选的12款优秀jQuery Ajax分页插件和教程
Aug 09 Javascript
Javascript中产生固定结果的函数优化技巧
Jan 16 Javascript
原生js实现fadein 和 fadeout淡入淡出效果
Jun 05 Javascript
JavaScript数组去重的3种方法和代码实例
Jul 01 Javascript
JS实现的表格行鼠标点击高亮效果代码
Nov 27 Javascript
Angular 4 指令快速入门教程
Jun 07 Javascript
vue组件详解之使用slot分发内容
Apr 09 Javascript
详解Node使用Puppeteer完成一次复杂的爬虫
Apr 18 Javascript
微信小程序MUI导航栏透明渐变功能示例(通过改变opacity实现)
Jan 24 Javascript
webpack4手动搭建Vue开发环境实现todoList项目的方法
May 16 Javascript
使用Vue实现调用接口加载页面初始数据
Oct 28 Javascript
记一次vue去除#问题处理经过小结
Jan 24 #Javascript
微信小程序MUI侧滑导航菜单示例(Popup弹出式,左侧滑动,右侧不动)
Jan 23 #Javascript
微信小程序MUI侧滑导航菜单示例(Popup弹出式,左侧不动,右侧滑动)
Jan 23 #Javascript
vue车牌号校验和银行校验实战
Jan 23 #Javascript
微信小程序map组件结合高德地图API实现wx.chooseLocation功能示例
Jan 23 #Javascript
微信小程序使用map组件实现检索(定位位置)周边的POI功能示例
Jan 23 #Javascript
使用javascript做时间倒数读秒功能的实例
Jan 23 #Javascript
You might like
神族 PROTOSS 概述
2020/03/14 星际争霸
SONY SRF-40W电路分析
2021/03/02 无线电
php中simplexml_load_string使用实例分享
2014/02/13 PHP
jQuery 动态酷效果实现总结
2009/12/27 Javascript
JS分页控件 可用于无刷新分页
2013/07/23 Javascript
javascript浏览器窗口之间传递数据的方法
2015/01/20 Javascript
Express实现前端后端通信上传图片之存储数据库(mysql)傻瓜式教程(二)
2015/12/10 Javascript
使用struts2+Ajax+jquery验证用户名是否已被注册
2016/03/22 Javascript
js实现select选择框效果及美化
2016/08/19 Javascript
值得分享的bootstrap table实例
2016/09/22 Javascript
Node.js学习入门
2017/01/03 Javascript
ionic+AngularJs实现获取验证码倒计时按钮
2017/04/22 Javascript
ReactNative中使用Redux架构总结
2017/12/15 Javascript
基于Vue2x实现响应式自适应轮播组件插件VueSliderShow功能
2018/05/16 Javascript
解决layui表格的表头不滚动的问题
2019/09/04 Javascript
layui form.render('select', 'test2') 更新渲染的方法
2019/09/27 Javascript
Vue实现页面添加水印功能
2019/11/09 Javascript
关于AngularJS中几种Providers的区别总结
2020/05/17 Javascript
[01:31:03]DOTA2完美盛典全回顾 见证十五项大奖花落谁家
2017/11/28 DOTA
[01:54]TI珍贵瞬间系列(三):翻盘
2020/08/28 DOTA
Python排序搜索基本算法之选择排序实例分析
2017/12/09 Python
python3.6.3+opencv3.3.0实现动态人脸捕获
2018/05/25 Python
Python实现多条件筛选目标数据功能【测试可用】
2018/06/13 Python
符合语言习惯的 Python 优雅编程技巧【推荐】
2018/09/25 Python
Python模块相关知识点小结
2020/03/09 Python
纯CSS3实现Material Design效果
2017/03/09 HTML / CSS
德国旅行、体验和活动的预订平台:Watado
2019/12/04 全球购物
数据库方面面试题
2012/04/22 面试题
母亲节演讲稿范文
2014/01/02 职场文书
大学军训感言200字
2014/02/26 职场文书
绿色校园广播稿
2014/10/13 职场文书
治庸问责工作总结
2015/08/11 职场文书
婚庆答谢词大全
2015/09/29 职场文书
python tkinter实现定时关机
2021/04/21 Python
MySQL中VARCHAR与CHAR格式数据的区别
2021/05/26 MySQL
适合后台管理系统开发的12个前端框架(小结)
2021/06/29 Javascript