资讯专栏INFORMATION COLUMN

mosquitto 与 websocket 的结合

tomener / 2888人阅读

摘要:前言作为一个消息代理客户端与服务端的通信时基于协议的而现在的主流应用时呈现在浏览器中这意味着用户与服务端只能通过或者这类浏览器能理解的协议传输所以后端还要建立一个代理层将协议传输的内容解析一下以协议发送到最后再由发送到硬件端在浏览器支持的协

前言

mosquitto 作为一个消息代理, 客户端与 mosquitto 服务端的通信时基于 MQTT 协议的, 而现在的主流 web 应用时呈现在浏览器中, 这意味着用户与服务端只能通过 HTTP 或者 HTTPS 这类浏览器能理解的协议传输, 所以后端还要建立一个代理层, 将 HTTP 协议传输的内容解析一下以 MQTT 协议发送到 mosquitto, 最后再由 mosquitto 发送到硬件端.

在浏览器支持的协议中, 还有一个适用于长连接的 WS 协议, 参考: 浏览器中常见网络协议介绍. 如果客户端直接通过 websocket 连接到 mosquitto 端, 那么就不需要中间的后端代理层. 后端只需要一个推送服务和控制系统就可以实现对客户端的监听, 控制, 推送(当然, 如果业务量巨大, 业务逻辑复杂, 代理层还是有必要的, 因为这样不但可以为 mosquitto 过滤一些不必要的业务, 而且可以做一些数据统计, 设计事件钩子).

在编译 mosquitto 和它的验证插件 mosquitto-auth-plug 的时候, 我注意到 mosquitto 有一个监听的 9001 端口, 事后查了一下, 发现 mosquitto 开放的这个端口是支持直接与客户端进行 websocket 通信的.

启用 mosquitto websocket 模式

其实纯粹的 MQTT 服务器是没有这个功能的, mosquitto 需要在编译的时候设置 configure.mk

WITH_WEBSOCKETS := yes

所幸的是, eclipse 官方的 docker 镜像 已经支持了 websocket 通信方式. 只需要在 mosquitto.conf 中启用:

port 1883
listener 9001
protocol websockets
使用 paho-mqtt.js 通过 websocket 与 mosquitto 通信

eclipse 提供了用于 浏览器客户端利用 javascript 和 mosquitto 进行 websocket 通信的 paho-mqtt.js, 这是这个 js 库的文档: Paho.MQTT DOC.

客户端与服务端的双通道通信

我们假设有客户端用户为 client, 服务端用户为 server. 为他们分配的主题与权限为:

 id | username |      topic         | rw 
----+----------+--------------------+----
  1 | client   | /p/client/upload   |  2
  2 | server   | /p/client/upload   |  2
  3 | client   | /p/client/download |  1
  4 | server   | /p/client/download |  2

那么 server 和 client 均可以在 /p/client/upload 读写. 我们约定只有 client 在 /p/client/upload 写, server 只读 /p/client/upload, 这个 topic 是用于 client 向 server 发送消息.

对于 topic /p/client/download, server 可读可写, client 只读, 这个 topic 是用于 client 接受 server 向下推送的消息, 具体的逻辑如下:

注意这里的 client 是对 /p/client/upload 具有可读可写权限的, 意味者它可以读取来自 /p/client/upload 的信息, 但是实际上这里没有人往这个主题发布消息(除非 client 自己往这里发消息), 所以 client 拥有可读权限也没有关系.

客户端的 javascript 通信例子

建议看一下这篇文章: Using MQTT Over WebSockets with Mosquitto, 它比较详细地介绍了客户端通过 websocket 于 mosquitto 服务器通信的方式.
比如对于 client.html:
先引入 paho-mqtt.js, 这里我们先用 cloudflare.com CDN上的这段 js:

下面是创建客户端 websocket 的例子:

var mqtt;
var host = "mosquitto";
var port = 9001;

// onConnect 事件
function onConnect() {
    console.log("connected.");
    var raw_message = "Hello World!";
    message = new Paho.MQTT.Message(raw_message);
    message.destinationName = "/p/client/upload";
    console.log("sending message: " + raw_message );
    mqtt.send(message);

    // 订阅 download topic
    var subOptions = {
        qos: 1,
        onSuccess: onSubscribe
    };
    mqtt.subscribe("/p/client/download", subOptions);
}

// 订阅主题成功事件
function onSubscribe(context) {
    console.log("subscribe success");
    console.log(context);
}

// 连接失败事件
function onFailure(message) {
    console.log("connect failed.");
}

// onMessageArrived 事件
function onMessageArrived(message) {
    console.log("new message arrived...");
    console.log(message.payloadString);
}


// 建立 MQTT websocket 连接
function MQTTconnect() {
    console.log("connecting to " + host + ":" + port);
    mqtt = new Paho.MQTT.Client(host, port, "clientid");
    var options = {
        timeout: 3,
        onSuccess: onConnect,
        onFailure: onFailure,
        userName: "client",
        password: "123456",
        mqttVersion: 4
    };
    mqtt.onMessageArrived = onMessageArrived;
    mqtt.connect(options);
}

这里我们利用 paho-mqtt.js 新建了一个 mqtt, 然后绑定 onSuccess(连接成功), onFailure(连接失败) onMessageArrived(消息到来)等事件, 之后用 options 里的配置连接到远程的 mosquitto 服务器. 连接成功后, client 向 server 发送一条消息到 /p/client/upload topic, 通知服务端已经建立连接. 发送之后 mqtt 又订阅 /p/client/download, 准备接受来自服务端的信息.

比如, 服务端可以这样向客户端推送消息:

import paho.mqtt.publish as publish
import time

HOST = "mosquitto"
PORT = 1883


if __name__ == "__main__":
    client_id = time.strftime("%Y%m%d%H%M%S", time.localtime(time.time()))
    publish.single(
        "/p/client/download", "hello mqtt", qos=2, hostname=HOST, port=PORT,
        client_id=client_id, auth={"username": "server", "password": "123456"})

这就是基于双通道的服务端于客户端通信

客户端与服务端的单通道通信

单通道通信原理类似, 但是由于客户端可能有多台设备, 比如手机端, 微信小程序端, PC 端. 那么身份的验证不能直接由 mosquitto 确定, 应该在消息体内确定. 比如我们用 json 作为消息的承载方式. 消息体可以这样:

{
    "timestamp": "1539141568",
    "client_id": "1001001",
    "message_type": "ping",
    "data": {"detail": "content"},
    "token": "auth_token"
}

这里应该按照具体的业务需求进行鉴权设计.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/42606.html

相关文章

  • mosquitto websocket 结合

    摘要:前言作为一个消息代理客户端与服务端的通信时基于协议的而现在的主流应用时呈现在浏览器中这意味着用户与服务端只能通过或者这类浏览器能理解的协议传输所以后端还要建立一个代理层将协议传输的内容解析一下以协议发送到最后再由发送到硬件端在浏览器支持的协 前言 mosquitto 作为一个消息代理, 客户端与 mosquitto 服务端的通信时基于 MQTT 协议的, 而现在的主流 web 应用时呈...

    joy968 评论0 收藏0
  • 基于MQTT物联网云测量解决方案

    摘要:本文是其中的一个解决方案。地址客户端服务端前端网页介绍,消息队列遥测传输是开发的一个即时通讯协议,有可能成为物联网的重要组成部分。必须用于在顶层分隔符之后,除了当自己指定时。 1. 问题描述 最近,本实验室大量上马云测量,云监控方面的项目,大概是属于物联网应用的一个分支。老板也有将旧有仪器改造的想法,所以要实现仪器设备的云控制。本文是其中的一个解决方案。 2. 技术选型 消息队列:M...

    张金宝 评论0 收藏0
  • 用 docker 部署 mosquitto 并编译 mosquitto-auth-plug

    摘要:再运行一次它往发送了一个消息我们可以看到就已经收到了总结我们成功地搭建了一个的消息代理服务并为它编译了可以供后续后端消息业务的开发详细代码也可以参考已经上传到的 mosquitto 的简介 mosquitto 是一个开源的轻量级消息代理服务, 支持 MQTT-3.1 和 MQTT-3.1.1, 采用发布订阅模式. mosquitto 目前广泛用于手机设备, 底端传感器, 嵌入式计算机的...

    maybe_009 评论0 收藏0
  • PHP 使用mosquiito

    摘要:近期业务需要,调研和使用基于协议的,开发一个消息推送系统。环境安装安装的扩展然后把加到重启编写代码,订阅为的消息想为,发布消息运行脚本发布消息脚本接受到消息并且打印出来脚本中,在收到消息后,会发布一个消息到为中,后台会接收消息 近期业务需要,调研和使用基于mqtt协议的mosquitto,开发一个消息推送系统。 环境:ubuntu 14.04,php7.1,mosquitto 安装mo...

    Developer 评论0 收藏0

发表评论

0条评论

tomener

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<