基於 WebSocket 的 MQTT


視頻說明:https://www.bilibili.com/video/BV1qf4y1n7js/?p=4

一般情況下客戶端使用TCP方式連接服務端,現在想使用瀏覽器作為客戶端連接服務端,需要使用WebSocket方式。

Windows 上 Mosquitto 設置支持WebSocket

先暫停Mosquitto服務:【服務】 -> 【Mosquitto Broker】停止

配置文件位置:"C:\Program Files\Mosquitto\mosquitto.conf"

配置語句

bind_address 0.0.0.0

listener 8083
protocol websockets

allow_anonymous true

配置語句說明

🟣 bind_address 0.0.0.0:表示允許任意網址訪問,(如果設置成 127.0.0.1,則表示只允許本機訪問,修改了 listener 后需要配置)

🟠 listener 8083:表示監聽 8083 端口,(只寫 listener,protocol 則默認是mqtt,mqtt協議沒有建議websocket的端口,emq建議8083,好多人使用9001)
🟠 protocol websockets:表示開放WebSocket協議連接,(listener 和 protocol 是成對出現的,只有 protocol 會報錯)

🟡 allow_anonymous true:表示允許匿名訪問,(windwos上,默認不配置任何listener,是true,配置了listener默認是false,所以要設置成true)

修改mosquitto.conf配置文件,會提示不允許修改,可以先復制出來,修改后再粘貼替換原文件。

CentOS7上 Mosquitto 設置支持WebSocket

修改配置文件 /etc/mosquitto/mosquitto.conf

bind_address 0.0.0.0

listener 8083
protocol websockets

重啟 Moqquitto

systemctl restart mosquitto

查看 Moqquitto 狀態

systemctl status mosquitto

防火牆開放相關端口:1883、8083

Mosquitto 配置:ubuntu

發現 mosquitto 新版本(2.0.15),安裝完后不能直接匿名登錄了。

添加配置

vi /etc/mosquitto/mosquitto.conf

添加配置,
💦 默認不允許匿名登錄
💦 原來默認的 1883 端口還要手動添加

allow_anonymous true

listener 1883
protocol mqtt

listener 9001
protocol websockets
# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

include_dir /etc/mosquitto/conf.d

allow_anonymous true

listener 1883
protocol mqtt

listener 9001
protocol websockets

多端口機制

說明:

listener 和 protocol 是成對出現的,表示:【端口-協議

當然可以增加多組【端口-協議】,比如

listener 8084

listener 8085
protocol websockets

listener 8086
protocol websockets

listener 8087
protocol mqtt

listener 8088

可以看到相關的提示

多端口作用

服務端(linux)配置多端口,可以實現一端是TCP連接,一端是WebSocket連接的互通,因為服務端維護的是一個訂閱樹

  • mosquitto:只有一個訂閱樹的服務端
  • 開發板:TCP連接的客戶端
  • 瀏覽器:WebSocket連接的客戶端

多端口可以配置不同策略,以應對不同場景,例如:

  • 讓端口A使用mqtt並且不啟用tls,
  • 讓端口B使用mqtt協議並且啟用tls,
  • 讓端口C使用websocket協議並且不啟用tls,
  • 讓端口D使用websocket並且啟用tls等等

當然也可以不配置它們(mosquitto使用默認參數,例如默認的協議為mqtt,默認不開啟tls等)。

客戶端連接:使用測試工具

MQTTX

在線網頁工具

MQTT WebSocket Toolkit
http://tools.emqx.io/

MQTT Websocket Client
http://mqtt.p2hp.com/websocket/
http://www.hivemq.com/demos/websocket-client/

客戶端連接:使用 Java Paho

修改一行代碼

options.setServerURIs(new String[]{"ws://127.0.0.1:8083/mqtt"});

客戶端連接:使用 mqtt.js

https://github.com/mqttjs/MQTT.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>MQTT over WebSocket</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/mqtt/4.2.8/mqtt.js"></script>
</head>

<body>

<div>
    發送的內容:
    <input id="send" type="text" style="width: 300px;height: 30px">
    <button id="sendButton">發送</button>
</div>

<div>
    收到的內容:
    <input id="receive" type="text" style="width: 300px;height: 30px">
</div>

<script type="module">

    const clientId = 'mqttjs_' + Math.random().toString(16).substr(2, 8)

    const host = 'ws://127.0.0.1:8083/mqtt'
    // const host = 'ws://broker.emqx.io:8083/mqtt'

    const options = {
        keepalive: 60,
        clientId: clientId,
        protocolId: 'MQTT',
        protocolVersion: 4,
        clean: true,
        reconnectPeriod: 1000,
        connectTimeout: 30 * 1000,
        // will: {
        //     topic: 'collector',
        //     payload: '異常斷開!',
        //     qos: 0,
        //     retain: false
        // },
    }

    const client = mqtt.connect(host, options)

    client.on('connect', () => {
        console.log('連接狀態:' + client.connected)
    })

    client.on('error', (err) => {
        console.log('連接錯誤: ', err)
        client.end()
    })

    client.on('reconnect', () => {
        console.log('重連中...')
    })

    // 當窗口關閉時,主動去關閉連接
    window.onbeforeunload = () => {
        client.end();
        return("ok");
    }

    // 訂閱消息:訂閱一個名為 collector QoS 為 0 的 主題
    client.subscribe('collector', {qos: 0}, function (error, granted) {
        if (error) {
            console.log(error)
        } else {
            console.log(`已訂閱主題: ${granted[0].topic}`)
        }
    })

    // 收到消息
    client.on('message', function (topic, payload, packet) {
        // Payload is Buffer
        console.log(`主題: ${topic}, 消息: ${payload.toString()}, QoS: ${packet.qos}`)
        document.getElementById('receive').value = `主題: ${topic}, 消息: ${payload.toString()}, QoS: ${packet.qos}`;
    })


    // 發布消息
    let sendButton = window.document.getElementById("sendButton");
    sendButton.addEventListener("click", () => {
        let message = document.getElementById('send').value;
        client.publish('collector', message, {qos: 1, retain: false, dup: true});
    })

</script>
</body>
</html>

效果

TLS

TLS(Transport Layer Security,安全傳輸層),TLS是建立在傳輸層TCP協議之上的協議,服務於應用層。

解決消息傳遞過程的安全問題:http,mqtt,傳輸過程中都是明文,IP訪問好像沒問題,域名訪問會出現偽造域名IP的問題(就是DNS返回錯誤的IP地址)

數字證書原理沒有弄懂,說操作吧

把域名解析到服務器IP地址

在騰訊雲上給一個域名申請SSL證書,然后把Apache證書文件放到/etc/mosquitto/certs/文件夾下

測試配置,mosquitto.conf

bind_address 0.0.0.0

listener 8883
protocol mqtt
cafile /etc/mosquitto/certs/root_bundle.crt
certfile /etc/mosquitto/certs/200180.xyz.crt
keyfile /etc/mosquitto/certs/200180.xyz.key
tls_version tlsv1.2

listener 9001
protocol websockets

listener 9883
protocol websockets
cafile /etc/mosquitto/certs/root_bundle.crt
certfile /etc/mosquitto/certs/200180.xyz.crt
keyfile /etc/mosquitto/certs/200180.xyz.key
tls_version tlsv1.2

服務器上開放相應防火牆端口

說明:ws的域名訪問連不上

💦 域名:200180.xyz
💦 TCP 端口: 1883
💦 TCP + TLS 端口: 8883
💦 WebSocket 端口:9001
💦 WebSocket + tls 端口:9883

客戶端連接時,
ws:// 改成 wss://
tcp:// 改成 lss://(Paho)

效果

實現過程

將 MQTT 通過 WebSockets 與 Mosquitto 結合使用

這文章莫名其妙,沒看明白

使用 WebSocket 連接 MQTT 服務器

知道了可以使用 MQTT.js 去連接

CentOS 7.4 搭建mosquitto服務器並配置tls/ssl websocket

原來使用 WebSocket 連接可以這樣配置

mosquitto的多端口機制及其使用

這個比較有啟發,原來是使用多端口機制,listener 和 protocol 要成對配置

mqtt+ssl服務搭建以及ws+wss支持

配置wss參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM