mqtt伺服器搭建實驗報告
1. 如何採用mqtt協議實現android消息推送
使用一個代理伺服器message broker,客戶端client連接上這個伺服器,然後告訴伺服器,可以接收哪些類型的消息,同時client也可以發布自己的消息,這些消息根據協議的內容,可以別的client獲取。這樣就實現了消息推送。消息推送是通過一定的技術標准或協議,在互聯網上通過定期傳送用戶需要的信息來減少信息過載的一項新技術。
如果想要使用消息推送,推薦使用深圳極光的消息推送系統。深圳極光是國內首個為移動應用開發者提供專業、高效的消息推送服務的產品。品牌成長的過程,就是與客戶肩並肩邁向成功的過程。極光將以市場為導向,以創新為動力,以技術為支持,不斷用心努力,為每一位尊貴的客戶提供極致的服務。
2. 黑群暉怎樣搭建MQTT伺服器
1、打開群暉Docker,注冊表搜索:mqtt;
2、點擊下載好的鏡像文件創建容器,輸入容器名字,點擊高級設置
3、勾選啟用自動重新啟動
4、點擊網路—-勾選與docker host相同的網路,點擊應用,一直下一步直到創建完成
3. 在雲伺服器上搭建了mqtt,為什麼手機連接不上mqtt,要怎麼做才能連接上求求大神幫忙
MQTT協議是廣泛應用的物聯網協議,使用測試MQTT協議需要MQTT的代理。有兩種方法使用MQTT服務,一是租用現成的MQTT伺服器,如阿里雲,網路雲,華為雲等公用的雲平台提供的MQTT服務,使用公用的MQTT伺服器的好處是省事,但如果僅僅用於測試學習還需要注冊帳號,靈活性差些,有的平台還需要付費。另一方法是自己使用開源的MQTT組件來搭建。
MQTT伺服器非常多,如apache的ActiveMQ,emtqqd,HiveMQ,Emitter,Mosquitto,Moquette等等。
這里介紹的是用輕量級的mosquitto開源項目來搭建一個屬於自己的MQTT伺服器。
第一步:需要安裝一台linux主機,這不多介紹,可以使用真機安裝也可以使用虛擬機安裝。如果僅僅是自己測試使用都可以。
第二步:下載mosquitto需要的依賴
sudo apt-get install libssl-devsudo apt-get install uuid-devsudo apt-get install cmake
第三步:下載mosquitto並解壓,現在mosquitto官網最新的版本是1.5.1
tar xzvf mosquitto-1.5.1.tar.gz
第四步:編譯
cd mosquitto-1.5.1/
make
make install
第五步:啟動mosquitto
./mosquitto -v
1535473957: mosquitto version 1.5.1 starting
1535473957: Using default config.
1535473957: Opening ipv4 listen socket on port 1883.
1535473957: Opening ipv6 listen socket on port 1883.
這時候mosquitto就會以默認的參數啟動。如果需要帶配置文件可以修改配置文件mosquitto.conf,
啟動時候加上參數 -c,
./mosquitto -c mosquitto.conf
可以看到,mosquitto監聽的埠為1883.
這時候我們的MQTT伺服器就搭建好了。可找一個mqtt客戶端來測試一下。
先發布一個主題「home/garden/fountain/2」
內容是「hello world」
這時候在mosquitto會列印出下面的log
535474247: New connection from 192.168.1.105 on port 1883.
1535474247: New client connected from 192.168.1.105 as MQTT_FX_Client (c1, k60).
1535474247: No will message specified.
1535474247: Sending CONNACK to MQTT_FX_Client (0, 0)
1535474307: Received PINGREQ from MQTT_FX_Client
1535474307: Sending PINGRESP to MQTT_FX_Client
1535474339: Received PUBLISH from MQTT_FX_Client (d0, q0, r0, m0, 'home/garden/fountain/2', ... (12 bytes))
1535474367: Received PINGREQ from MQTT_FX_Client
1535474367: Sending PINGRESP to MQTT_FX_Client
訂閱主題「home/garden/fountain/2」
可以看到收到了自己發布的消息。
用wireshark抓包
可以看到抓到了一個MQTT的publish的報文。
4. Android 中使用MQTT(第一篇)
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)是IBM開發的一個即時通訊協議。它是一種發布/訂閱,極其簡單和輕量級的消息傳遞協議,專為受限設備和低帶寬,高延遲或不可靠的網路而設計。它的設計思想是輕巧、開放、簡單、規范,易於實現。這些特點使得它對很多場景來說都是很好的選擇,特別是對於受限的環境如機器與機器的通信(M2M)以及物聯網環境。相對於XMPP,MQTT更加輕量級,並且佔用的寬頻低。
MQTT協議有以下特點:
那麼問題來了?重連連接成功後重復接收到最後一條消息
MQTT推送消息訂閱端重復接收問題。
(背景)訂閱端斷開的時候,發布端多次推送消息。
(現象)訂閱端啟動時,接收到最後一條推送消息有兩次;即使Qos設置為2;依然是兩次。
經排查是因為
MqttMessage的Retained設置為了true;
該值很多文章上只說了是 消息保留機制,若設置為true,mqtt伺服器會保留每次發布的消息;較少提到 若訂閱某主題的客戶端重啟,則會把此主題之前發布的消息重新推送到客戶端。該值默認為false;去掉修改該值即可
那麼問題來了?重連連接後手動那麼多遺漏的消息,怎麼選擇只接收最新的一條消息呢?
MQTT推送消息訂閱端重復接收問題。
(背景)訂閱端斷開的時候,發布端多次推送消息。
(現象)訂閱端啟動時,接收到msg1,msg2,msg3 (這三個消息都是同一個類型消息,只需要處理最新的msg3就好,不然界面會刷新三次)這個誰有什麼好辦法沒呢?
GitHub地址: https://github.com/eclipse/paho.mqtt.android
mqtt的官方文檔: http://mqtt.org/documentation
Github上有中文翻譯: https://github.com/mcxiaoke/mqtt
在mole的build.gradle文件中添加依賴
在 AndroidManifest.xml 添加限權
在 AndroidManifest.xml 注冊Service (MyMqttService為自己寫的服務,下文會講到)
5. 如何用mosquitto搭建伺服器
Mosquitto是一款實現了消息推送協議MQTT v3.1的開源消息代理軟體,提供輕量級的,支持可發布/可訂閱的的消息推送模式,使設備對設備之間的短消息通信變得簡單,比如現在應用廣泛的低功耗感測器,手機、嵌入式計算機、微型控制器等移動設備。
Mosquitto官網:
MQTT協議:
客戶端連接日誌
1403334375: New connection from 121.201.8.163 on port 1883.
1403334375: New client connected from 121.201.8.163 as zhoujing (c0, k60, ujoyo).
1403334375: Sending CONNACK to zhoujing (0)
以上是一個客戶端正常連接的日誌。
第一行:伺服器收到一個新的連接請求
1403334375: 表示連接的時間點
121.201.8.163: 客戶端的IP地址
1883: 連接的伺服器埠號
第二行:伺服器為客戶端建立連接
zhoujing (c0, k60, ujoyo): 客戶端連接指定的ClientID為'zhoujing'
c0: 表示cleanSession=false,不清除session
k60: 表示keep-alive=60s
ujoyo: 表示使用的伺服器賬號為joyo
第三行:發送連接ACK包給客戶端
客戶端訂閱過程日誌
1403334375: Received SUBSCRIBE from zhoujing
1403334375: jiji/chat/9 (QoS 2)
1403334375: zhoujing 2 jiji/chat/9
1403334375: Sending SUBACK to zhoujing
第一行:伺服器收到一個來自ClientID為zhoujing的訂閱請求
第二行:伺服器識別zhoujing訂閱的主題為 jiji/chat/9,指定的QOS=2(有且只發送一次)
第三行:給ClientID=zhoujing客戶端發送訂閱ACK回包
伺服器發送內容給客戶端日誌
1403334378: Sending PUBLISH to zhoujing (d0, q2, r0, m1, 'jiji/chat/9', ... (396 bytes))
1403334378: Received PUBREC from zhoujing (Mid: 1)
1403334378: Sending PUBREL to zhoujing (Mid: 1)
1403334378: Received PUBCOMP from zhoujing (Mid: 1)
第一行:伺服器正在發送一個消息給ClientID=zhoujing的客戶端,消息體大小為396 bytes,消息主題為『jiji/chat/9』
(d0, q2, r0, m1)的解釋, 以下參數具體含義,參考MQTT協議
d: 表示mqtt報頭的DUP欄位
q: 表示的QOS欄位
r: 表示的是RETAIN
m: 表示的是消息ID,即mid
第二行:發布收稿階段,有保證的交付第一部分
第三行:出版發行階段,有保證的交付第二部分
第四行:發布完成,有保證的交付第三部分,至此一個內容發部過程完成
客戶端主動斷開連接的日誌
客戶端主動斷開連接的只有一行日誌,很簡單。如下所示:
1403334380: Received DISCONNECT from JY_API_PUSH_CLIENT
接收客戶端發布內容的過程日誌
1403334389: Received PUBLISH from JY_API_PUSH_CLIENT (d0, q2, r0, m1, 'jiji/chat/9', ... (396 bytes))
1403334389: Sending PUBREC to JY_API_PUSH_CLIENT (Mid: 1)
1403334389: Received PUBREL from JY_API_PUSH_CLIENT (Mid: 1)
1403334389: Sending PUBCOMP to JY_API_PUSH_CLIENT (Mid: 1)
第一行:接收來自ClientID=JY_API_PUSH_CLIENT的發布請求,發布的消息主題為'jiji/chat/9',消息大小為396 bytes
第二行:伺服器發送PUBREC給客戶端,此過程與發送消息給客戶端正好對稱,只不過是Received和Sending的對象反過來而已
第三行:伺服器接收到客戶端已經釋放的命令,內容交付第二步完成
第四行:通知客戶端,接收完成,至此一個消息發布完成,內容交付第三步完成
同一個ClientID重復連接時
1403334510: New connection from 121.201.7.150 on port 1883.
1403334510: Client JY_API_PUSH_CLIENT already connected, closing old connection.
接收客戶端心跳包
1403336716: Received PINGREQ from 36383A64663A6464003V0
1403336716: Sending PINGRESP to 36383A64663A6464003V0
客戶端連接超時,伺服器主動清除連接信息
1403336671: Client 33303A33393A3236003V0 has exceeded timeout, disconnecting.
客戶端socket異常時的日誌
1403337602: Socket error on client 351BBJKFX62C1, disconnecting.
1403337602: Socket error on client 351BBJKFX62C0, disconnecting.
6. 使用 Node-RED 處理 MQTT 數據
本文將介紹使用 Node-RED 連接到 MQTT 伺服器,並對 MQTT 數據進行過濾和處理後再將其發送至 MQTT 伺服器的完整操作流程。讀者可以快速了解如何使用 Node-RED 對 MQTT 數據進行簡單的流處理。
Node-RED 無論是在你本地的電腦上,還是樹莓派等設備,亦或是雲端伺服器,都可以快速安裝和使用,下面將使用兩種比較常見的安裝方式:
使用 npm 進行全局安裝:
使用 Docker 進行安裝:
如果使用的是 npm 進行的全局安裝,那麼在提示安裝成功後,只需要在全局運行 node-red 命令就可以立即啟動 Node-RED。
無論是使用 Docker 還是 npm 在啟動成功後,我們只需要打開瀏覽器,輸入當前地址加 1880 埠號,即可打開 Node-RED 的瀏覽器編輯器頁面,例如在本地運行的話,打開瀏覽器,輸入 http://127.0.0.1:1880,當看到如下圖所示頁面後,說明 Node-RED 已經成功啟動:
本文將使用 EMQ 提供的 免費公共 MQTT 伺服器,該服務基於 MQTT 物聯網雲平台 - EMQX Cloud 創建,伺服器接入信息如下:
在下面的功能演示中,我們將提供一個使用 Node-RED 來處理接收到的包含溫濕度信息的 JSON 數據,然後對溫度值進行規則判斷,當溫度發生改變的時候,就將當前發生改變的溫度值通過 MQTT 再次發送出去的簡單使用案例。
我們首先在左側菜單欄中,拖拽一個 MQTT in 的節點到頁面中,雙擊節點後,右側出現一個編輯 MQTT 節點的配置頁面,我們根據內容提示,新建一個連接信息後,再填入 MQTT 的其它連接信息後,點擊 Done 按鈕後,即可保存該節點信息。
接入數據:我們拖拽一個 JSON 節點到頁面中,可以在 JSON 節點的配置頁面中,配置一個 Action,我們設置為 Always convert to JavasScript Object ,因為我們無法確定發送過來的數據是一個 JSON 格式的數據還是一個 JSON 字元串,因此第一步都將接收到的消息進行一個 JSON 轉換。配置完成後,我們將該節點與 MQTT in 節點進行連接。
過濾數據
我們配置完成格式化發送過來的消息數據後,我們就可以拖拽一個 filter 節點到頁面中,同樣雙擊節點後,在配置頁面中配置規則,我們先選擇一個 Mode,我們設置為 blcok unless value changes ,過濾規則為需要當前接收到數據的值發生改變,因為目前數據為 JSON 格式,我們判斷的是 JSON 數據內的某一個值,因此我們需要在 Property 這里設置值為 msg.payload.temperature 配置完成後我們點擊 Done 按鈕來保存數據過濾節點的配置,最後將該節點連接到上一步配置完成後的 JSON 節點。
使用模版
當過濾完數據後,同樣拖拽一個 template 節點到頁面中,雙擊節點後來配置模版內容,使過濾完成後的數據,能通過模版將數據進行輸出。當然也可以不需要這個步驟,直接將過濾後的數據進行輸出。
完成以上對數據的處理和過濾後,最後我們再來將處理完成後的數據使用 MQTT 將其發送出去,拖拽一個 MQTT out 的節點到頁面中,填入和 MQTT in 節點相同的連接信息,配置一個用戶接收數據的 Topic,最後保存完成後,再將其和 template 節點進行連接,點擊右上角的 Deploy 按鈕,即可對當前規則應用進行在線部署。
在完成整個流數據處理的功能編排以後,我們使用 MQTT 5.0 客戶端工具 - MQTT X 來測試和驗證該功能的可用性。我們新建一個連接,連接到剛才在 Node-RED 中配置的 MQTT 雲服務地址,然後輸入 MQTT in 節點內的 Topic 來發送一條消息,使 Node-RED 能夠接收到我們發送的 MQTT 數據。
然後我們再在 MQTT X 中訂閱一個在 MQTT out 節點內配置的 Topic,用於接收處理過的消息數據。當發送一條包含了溫濕度的消息數據後,我們可以接收到一條根據我們設定的消息模版發送過來的消息,再次發送就無法接收到。
因為此時溫度值沒有發生變化,當我們再次修改溫度值後,就會發現我們又接收到了一條包含提醒溫度值發生變化的消息。
至此,我們完成了安裝並使用 Node-RED 連接到 MQTT 雲服務,以及對 MQTT 消息數據進行過濾和處理,最後再將處理完成後的數據消息發送至 MQTT 伺服器的全部流程。
Node-RED 的交互和使用方式,即用 UI 方式描述通用業務邏輯,可以降低非專業開發人員的上手門檻,使用一個可視化工具快速地創建需要的復雜執行任務,可以通過簡單 Node 即節點連接構建出復雜的任務,特別是針對一些物聯網的應用場景,都很有幫助。
7. Android MQTT 通信
MQTT 協議 是基於發布/訂閱模式的物聯網通信協議,憑借簡單易實現、支持 QoS、報文小等特點,占據了物聯網協議的半壁江山。
常用於 IOT 物聯網和一些需要服務端主動通知客戶端的場景。
1. 導入依賴
2. 創建 MqttHelper 輔助類,設置回調監聽
3. 連接 MQTT
連接成功或失敗,以及中途的連接掉線,會觸發 OnMqttStatusChangeListener 回調
4. MQTT 連接狀態監聽
5. MQTT 收發消息監聽
onSubMessage 訂閱的消息回調,因為存在訂閱多個 topic 的情況,所以回調能知道是來自哪個 Topic 的消息;
onPubMessage 發布的消息回調,用於確認發布的消息是否發送成功。
6. MQTT 訂閱 Topic
需要在 MQTT 連接成功後才能訂閱 topic,否則訂閱 Topic 不成功,收不到對應消息
7. MQTT 取消訂閱 Topic
8. MQTT 發布消息
9. MQTT 斷開連接
10. 通知設置
由於 MQTT 啟動了一個 Service,而 Android 8.0 以上對於後台 Service 限制時長 5 秒;所以將 MqttService 綁定到 Notification 上成為了一個前台通知;通知的標題和內容顯示可以在 strings.xml 中設置,對應屬性如下:
Android 8.0 及以上開啟前台服務綁定到通知,8.0 以下默認不啟用,可將 mqtt_foreground_notification_low_26 設為 true,將 8.0 以下設備也開啟前台通知服務
創建 MQTT 實例時需要傳送參數 MqttOptions,下面將介紹下部分參數;
1. Topic
MQTT 是一種發布/訂閱的消息協議, 通過設定的主題 Topic,
發布者向 Topic 發送的 payload 負載消息會經過伺服器, 轉發到所有訂閱襪橋
該 Topic 的訂閱者
通配符 : 假想移動端消息推送場景,有的系統消息是全體用戶接收,有的消息是 Android 或 iOS 設備接收, 又或者是某些消息具體推送到用戶,當然, 對應的多種類型消息可以通過多訂閱幾個對應的 Topic 解決,也可以使用通配符;
通配符有兩個, " + " 和 " # ", 與正斜杠 " / " 組合使用;加號只能表示一級Topic, 井號可以表示任意層級 Topic; 例如: 訂閱 Topic為 " System/+ ", 發布者發布的 Topic 可以是 System、System/Android、System/iOS; 但是不能是 System/iOS/123, 而訂閱的 Topic 如果是" System/# " 則可以收到;
注意,只有訂閱的 Topic 才可以使用 通配符, 發布和遺囑的 Topic 不能包含通配符.
2. ClientID
發布者和訂閱者都是屬於客戶端, 客戶端與服務端建立連接之後,發送的第一個報文消息必須是 Connect 消息隱好缺,而 Connect 的消息載荷中必須包含 clientID 客戶端唯一標識;
如果兩個客戶端的 clientID 一樣, 則服務端記錄第一個客戶端連接之後再收到第二個客戶端連接請求,則會向一個客戶端發送 Disconnect 報文斷開連接, 並連接第二個客戶端, 而如果此時設置了自動重連, 第一個客戶端再次連接,服務端又斷開與第二個的連接, 連上第一個客戶端, 如此將導灶辯致兩個客戶端不斷的被擠掉重連.
注意: clientID 使用的字元最好是 大小寫字母和數字, 長度最好限制在[1, 23] 之間;
3. 遺囑消息
可選參數, 客戶端沒有主動向服務端發起 disconnect 斷開連接消息,然而服務端檢測到和客戶端之間的連接已斷開, 此時服務端將該客戶端設置的遺囑消息發送出去
應用場景: 客戶端因網路等情況掉線之後, 可以及時通知到所有訂閱該遺囑 Topic 的客戶端;
遺囑 Topic 中不能存在通配符.
4. Session
客戶端和服務端之間建立的會話狀態, 一般用於消息保存, 如果設置清除 Session,則每次客戶端和服務端建立連接會創建一個新的會話,之前連接中的消息不能恢復,
而設置不清除會話, 對應發布者發送的 qos 為 1和2 的消息,還未被訂閱者接收確認,則需要保存在會話中, 以便訂閱者下次連接可以恢復這些消息;
注意: Session 存儲的消息是保存在內容中的, 所以如果不是重要的消息,最好是設置清除 Session, 或者設置 qos = 0;
5. 心跳包
標識客戶端傳輸一次控制報文到下一次傳輸之間允許的空閑時間;在這段時間內,如果客戶端沒有其他任何報文發送,必須發送一個 PINGREQ 報文到伺服器,而如果服務端在 1.5 倍心跳時間內沒有收到客戶端消息,則會主動斷開客戶端的連接,發送其遺囑消息給所有訂閱者。而服務端收到 PINGREQ 報文之後,立即返回 PINGRESP 報文給客戶端
心跳時間單位為秒,佔用2個位元組,最大 2^16 - 1 = 65535秒(18小時12分鍾15秒),設置為 0 表示不使用心跳機制; 心跳時間一般設置為幾分鍾或幾十秒即可,時間短點可以更快的發出遺囑消息通知掉線,但是時間短會增加消息頻率,影響服務端並發; 微信長連接為 300 秒,而三大運營商貌似也有個連接時間最小的為 5 分鍾。
6. qos
服務質量等級 qos 對應兩部分,一是客戶端到服務端發送的消息, 一是服務端到客戶端訂閱的消息; 從發布者到訂閱者實際 qos 為兩段路中 qos 最小的。
qos 可選值 0(最多交付一次)、1(最少交付一次)、2(正好交付一次);
qos = 0 :接收方不發送響應,發送方不進行重試;發送方只管發一次,不管是否發成功,也不管接收方是否成功接收,適用於不重要的數據傳輸;
qos = 1 :確保消息至少有一次到達接收方,發送方向接收方發送消息,需要等待接收方返回應答消息,如果發送方在一定時間之內沒有收到應答,發送方繼續下一次消息發送,直到收到應答消息,刪除本地消息緩存,不再發送;所以接收方可能收到1-n次消息;適用於需要收到所有消息,客戶端可以處理重復消息。
qos = 2 :確保消息只一次到達接收方,發送方和接收方之間消息處理流程最復雜;
Mqtt Qos 深度解讀 和 MQTT協議QoS2 准確一次送達的實現
7. payload 負載消息
位元組流類型, 是 MQTT 通信傳輸的真實數據
8. 保留消息
發布消息時設置, 對應參數 retain, 服務端將保留對應 Topic 最新的一條消息記錄; 保留消息的作用是每次客戶端連接上線都會收到其 Topic 的最後一條保留消息, 所以可能存在網路不穩定,頻繁掉線重連,每次重連重復收到保留消息;
可以向對應的 Topic 發送一條 空消息,用於清除保留消息。
MQTT 服務搭建 Apache Apollo 伺服器 搭建 MQTT 服務
Github 倉庫
mqtt 協議
8. 如何通過php實現mqtt協議
MQTT是一個輕量級的消息發布/訂閱協議,它是實現基於手機客戶端的消息推送伺服器的理想解決方案。
我們可以從這里下載該項目的實例代碼,並且可以找到一個採用PHP書寫的伺服器端實現。
架構如下所示: