在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判断chrome浏览器的方法
Mar 26 Javascript
使用原生js实现页面蒙灰(mask)效果示例代码
Jun 20 Javascript
jQuery实现订单提交页发送短信功能前端处理方法
Jul 04 Javascript
js实现导航吸顶效果
Feb 24 Javascript
js a标签点击事件
Mar 30 Javascript
vue如何引用其他组件(css和js)
Apr 13 Javascript
AngularJS实现的回到顶部指令功能实例
May 17 Javascript
js学习总结_轮播图之渐隐渐现版(实例讲解)
Jul 17 Javascript
p5.js入门教程之小球动画示例代码
Mar 15 Javascript
ES6使用新特性Proxy实现的数据绑定功能实例
May 11 Javascript
关于better-scroll插件的无法滑动bug(2021通过插件解决)
Mar 01 Javascript
JavaScript offset实现鼠标坐标获取和窗口内模块拖动
May 30 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
常用星际术语索引(新手指南)
2020/03/04 星际争霸
PHP 事务处理数据实现代码
2010/05/13 PHP
php将HTML表格每行每列转为数组实现采集表格数据的方法
2015/04/03 PHP
php求一个网段开始与结束IP地址的方法
2015/07/09 PHP
php四种定界符详解
2017/02/16 PHP
thinkPHP5框架闭包函数与子查询传参用法示例
2018/08/02 PHP
laravel实现按时间日期进行分组统计方法示例
2019/03/23 PHP
PHP字符串和十六进制如何实现互相转换
2020/07/16 PHP
jquery ajax 调用失败的原因示例介绍
2013/09/27 Javascript
JS实现金额转换(将输入的阿拉伯数字)转换成中文的实现代码
2013/09/30 Javascript
js实现砖头在页面拖拉效果
2020/11/20 Javascript
Mac 安装 nodejs方法(图文详细步骤)
2017/10/30 NodeJs
node实现登录图片验证码的示例代码
2018/04/20 Javascript
详解Webstorm 下的Angular2.0开发之路(图文)
2018/12/06 Javascript
vue+Element-ui实现分页效果实例代码详解
2018/12/10 Javascript
jstree中的checkbox默认选中和隐藏示例代码
2019/12/29 Javascript
使用Vue-cli 中为单独页面设置背景图片铺满全屏
2020/07/17 Javascript
[04:04]显微镜下的DOTA2第六期——电影级别的华丽团战
2014/06/20 DOTA
python中使用PIL制作并验证图片验证码
2018/03/15 Python
python3 json数据格式的转换(dumps/loads的使用、dict to str/str to dict、json字符串/字典的相互转换)
2019/04/01 Python
windows安装TensorFlow和Keras遇到的问题及其解决方法
2019/07/10 Python
在PyCharm的 Terminal(终端)切换Python版本的方法
2019/08/02 Python
python获取网络图片方法及整理过程详解
2019/12/20 Python
python第三方库学习笔记
2020/02/07 Python
使用python处理题库表格并转化为word形式的实现
2020/04/14 Python
CSS3 Notes: -webkit-box-reflect实现倒影的实例
2016/12/08 HTML / CSS
css3 实现滚动条美化效果的实例代码
2021/01/06 HTML / CSS
英国浴室洗脸盆购物网站:Click Basin
2018/06/08 全球购物
餐饮主管岗位职责
2013/12/10 职场文书
优秀的自荐信要注意哪些
2014/01/03 职场文书
会计求职信范文
2014/05/24 职场文书
讲文明知礼仪演讲稿
2014/09/13 职场文书
办公室个人总结
2015/02/28 职场文书
驳回起诉裁定书
2015/05/19 职场文书
《童年的发现》教学反思
2016/02/18 职场文书
JS监听Esc 键触发事键
2021/04/14 Javascript