1、简介
除了 http(向服务器发送请求接收数据)、websocket(与服务器建立双向通信的通道),这里提供了一种基于 websocket 、发布订阅模式的双工通信方式。
- 发布订阅:这是一种通信的模式,最常见的实践是基于MQTT。简单来说就A向B订阅一个主题(topic),订阅之后 A 可以收到 B 关于这个主题的消息推送;同时 A 也可以在这个主题向 B 发送消息(发布过程),从而完成双向的通信。本文中的 A 就是浏览器,B 就是目标服务器。
- mqttws31.js: 这个库基于 websocket 封装了一套发布订阅模式的通信方式。
- 该库是用于浏览器的,node.js 服务可以使用 mqtt.js。
下载:
方式一:https://www.cdnpkg.com/paho-mqtt/file/mqttws31.js/?id=59394
方式二:https://download.csdn.net/download/m0_67793437/89532428
上面两种方式都可以获取到,方式一是能找到的在线资源;方式二是我上传CSDN的,两种都可以用(实际项目中已使用过)。区别在于:方式二添加了重连机制的代码, 感兴趣的可以拉下来比较看一下。
引入:通过 CDN 和 源代码本地引入都可。
下面代码是基于方式二的引入方式
2、初始化、连接
// 初始化 client 对象
this.client = new Paho.MQTT.Client(
host, // 主机号 或 服务器的 hostname
port, // 端口
clientId // 客户端id(与服务器端规定协议)
);
// 连接
this.client.connect({
invocationContext: { //调用上下文
host: host,
port: port,
path: this.client.path,
clientId: 'text'
},
useSSL: window.location.protocol == 'https:' ? true : false, //是否使用 ssl 加密(就是 ws 或 wss)
cleanSession: false, //是否清除 session
keepAliveInterval: 20, //心跳保活间隔
reconnect: true, //是否启用重连
userName: , // 用户名
password: , // 用户密码(与服务器端定制加密规则)
onSuccess: () => { // 链接成功回调
console.log('mqtt 链接成功')
},
onFailure: (e) => { // 链接失败回调
console.log('mqtt 链接失败')
},
onReconnect: (e) => { // 重连成功回调
console.log('重连成功')
}
})
2.1、实例化 client 对象
库文件引入后,在全局挂载了 Paho 这个对象,new Paho.MQTT.Client() 实例化得到 client对象;
这里主要注意一下 new Paho.MQTT.Client() 的传参,源代码里标准的是4个参数:
host, port, path, clientId => 主机号、端口、路径、客户端id
- 若只传2个参数,则:uri,clientId => 完整路径、客户端id ( 完整路径可以解析出 host、port、path,例:wss://192.168.12.36:8080/mqtt )
- 若只传3个参数,则:host,port,clientId => 这里的 path 路径默认是 "/mqtt,host 可以是主机号(例:192.168.12.45)也可以是域名的 hostname (例:baohui.lon.com),若主机直接是域名加路径,这里的 port 可以写默认端口(http -> 80, https -> 443)
2.2、client.connect 连接
初始化完成,调用实例对象 client 身上的 connect() 方法开始连接,具体参数可见上文。
3、方法说明
this.client.subscribe(filter, subscribeOptions)
// filter: 订阅的 topic ,subscribeOptions:订阅配置,可不传
this.client.unsubscribe(filter, unsubscribeOptions)
// filter: 取消订阅的 topic ,subscribeOptions:订阅配置,可不传
this.client.send(topic, payload, qos, retained)
// topic:主题
// payload:待发送数据
// qos:频率(非必选)
// retained:是否保留,若 true 则服务端同步该消息给其他该主题的订阅者(非必选)
// 也可以只传一个参数,例如:
messageContent = JSON.stringify(messageContent)
let message = new Paho.MQTT.Message(messageContent);
message.destinationName = topic;
message.retained = true;
this.client.send(message)
// 断开连接
this.client.disconnect()
// 是否连接成功
this.client.isConnected()
4、事件
// 注册 接收到消息 的回调
this.client.onMessageArrived = e => {
e.destinationName // 主题
e.payloadString || e.payload; // 数据内容
}
//注册连接断开处理事件
this.client.onConnectionLost = (e) => {
console.log('mqtt链接断开')
console.log(e)
}
//注册 发送消息送达 事件
this.client.onMessageDelivered = (e) => {
console.log(e)
}
//注册 连接成功 事件
this.client.onConnected = (e) => {
console.log(e)
}
5、使用
以上就是这个库的最基本使用,如果想在项目中使用,可以进行二次封装。我的思路是实现一构造函数,通过实例化其对象创造一次连接,对象身上包含必要的属性和方法,当订阅了某一主题,收到推送调用相应的回调函数。
重连机制:贴下源代码
/** * Reconnect when this is invoked by the timer. */ ClientImpl.prototype._reconnect = function () { this._trace("Client._reconnect"); if (!this.connected) { this._reconnecting = true; this.sendPinger.cancel(); this.receivePinger.cancel(); if (this._reconnectInterval < 60) this._reconnectInterval += 5; if (this.connectOptions.uris) { this.hostIndex = 0; this._doConnect(this.connectOptions.uris[0]); } else { this._doConnect(this.uri); } } }
在 _reconnectInterval 的基础上,以每次增加 5s 的递增频率进行重连请求。
- 若采取第一种方式引入,需要自己添加重连机制,具体实现就是监听连接断开的事件,再在回调里面重新connect(),注册频率可写逻辑。
//注册连接断开处理事件 this.client.onConnectionLost = (e) => { console.log('mqtt链接断开') console.log(e) if (e.errorCode !== 0) { reconnect = setInterval(() => { this.client.connect({ // 、、、 onSuccess: () => { // 链接成功回调 if(reconnect)clearInterval(reconnect) reconnect = null console.log('mqtt 链接成功') }, }); }, 1000); } }