mqttws31.js 库文件使用与说明(基于 websocket 的前后端消息发布订阅)

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);
    }
}

 

 

 

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Undertow实现WebSocket前后端消息推送,可以按照以下步骤进行: 1. 在后端实现WebSocket处理器,代码如下: ```java import io.undertow.server.HttpServerExchange; import io.undertow.websockets.core.*; import io.undertow.websockets.spi.WebSocketHttpExchange; import io.undertow.websockets.spi.WebSocketSession; public class WebSocketHandler implements WebSocketConnectionCallback { @Override public void onConnect(WebSocketHttpExchange exchange, WebSocketChannel channel) { // WebSocket连接建立时触发 System.out.println("WebSocket连接建立"); // 创建WebSocket会话 WebSocketSession session = new UndertowWebSocketSession(channel); // 将WebSocket会话保存到会话管理器中 WebSocketSessionManager.addSession(session); // 注册WebSocket消息处理器 channel.getReceiveSetter().set(new WebSocketMessageHandler(session)); channel.resumeReceives(); } } class WebSocketMessageHandler implements WebSocketCallback<WebSocketChannel> { private WebSocketSession session; public WebSocketMessageHandler(WebSocketSession session) { this.session = session; } @Override public void onError(WebSocketChannel channel, Throwable throwable) { // WebSocket出错时触发 System.out.println("WebSocket出错"); throwable.printStackTrace(); } @Override public void onClose(WebSocketChannel channel, StreamSourceFrameChannel channel1) throws IOException { // WebSocket连接关闭时触发 System.out.println("WebSocket连接关闭"); // 从会话管理器中删除WebSocket会话 WebSocketSessionManager.removeSession(session); } @Override public void onFullTextMessage(WebSocketChannel channel, BufferedTextMessage message) { // 收到完整的文本消息时触发 System.out.println("收到文本消息:" + message.getData()); // 处理WebSocket消息 // ... } } ``` 2. 在Undertow服务器中添加WebSocket处理器,代码如下: ```java import io.undertow.Handlers; import io.undertow.Undertow; import io.undertow.server.RoutingHandler; import io.undertow.server.handlers.PathHandler; import io.undertow.server.handlers.resource.ClassPathResourceManager; import io.undertow.server.handlers.resource.ResourceHandler; import io.undertow.server.handlers.resource.ResourceManager; import io.undertow.server.handlers.websocket.WebSocketProtocolHandshakeHandler; public class WebSocketServer { public static void main(String[] args) { // 创建Web资源管理器 ResourceManager resourceManager = new ClassPathResourceManager(WebSocketServer.class.getClassLoader(), "web"); // 创建Web资源处理器 ResourceHandler resourceHandler = new ResourceHandler(resourceManager); // 创建WebSocket处理器 WebSocketConnectionCallback callback = new WebSocketHandler(); WebSocketProtocolHandshakeHandler websocketHandler = new WebSocketProtocolHandshakeHandler(callback); // 创建路由处理器 RoutingHandler routingHandler = Handlers.routing() .get("/", resourceHandler) .get("/{path}", resourceHandler) .get("/websocket", websocketHandler); // 创建路径处理器 PathHandler pathHandler = Handlers.path(routingHandler) .addPrefixPath("/", resourceHandler); // 创建Undertow服务器 Undertow server = Undertow.builder() .addHttpListener(8080, "localhost") .setHandler(pathHandler) .build(); // 启动Undertow服务器 server.start(); } } ``` 3. 在前端使用WebSocket连接到后端,代码如下: ```javascript var websocket = new WebSocket("ws://localhost:8080/websocket"); websocket.onopen = function() { console.log("WebSocket连接建立"); }; websocket.onclose = function() { console.log("WebSocket连接关闭"); }; websocket.onerror = function() { console.log("WebSocket出错"); }; websocket.onmessage = function(event) { console.log("收到文本消息:" + event.data); }; ``` 4. 在后端向前端发送消息,代码如下: ```java import io.undertow.websockets.core.*; import io.undertow.websockets.spi.WebSocketSession; public class WebSocketSessionManager { private static Set<WebSocketSession> sessions = new HashSet<>(); public static void addSession(WebSocketSession session) { sessions.add(session); } public static void removeSession(WebSocketSession session) { sessions.remove(session); } public static void sendMessage(String message) { for (WebSocketSession session : sessions) { try { session.send(new StringWebSocketMessage(message)); } catch (IOException e) { e.printStackTrace(); } } } } ``` 调用`WebSocketSessionManager.sendMessage()`方法即可向所有前端客户端发送消息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值