視頻說明: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 結合使用
這文章莫名其妙,沒看明白
知道了可以使用 MQTT.js 去連接
CentOS 7.4 搭建mosquitto服務器並配置tls/ssl websocket
原來使用 WebSocket 連接可以這樣配置
這個比較有啟發,原來是使用多端口機制,listener 和 protocol 要成對配置
配置wss參考