IOT必备之MQTT结构分析,不进来看看?【后附源码】
全網(wǎng)唯一物聯(lián)網(wǎng)MQTT協(xié)議報文
結(jié)構(gòu)分析以及基于C#代碼的報文組裝實現(xiàn)
介紹
MQTT是一種基于TCP/IP協(xié)議的應用層協(xié)議,它規(guī)定了不同應用之間進行數(shù)據(jù)交換時的傳送格式。既然是協(xié)議,理論上可以被任何開發(fā)語言實現(xiàn)它,以運行在任何平臺,這個特性就可以將所有可聯(lián)網(wǎng)的物品通過此協(xié)議的方式進行數(shù)據(jù)通信,這是其一,之所以被物聯(lián)網(wǎng)所青睞,還因為它的幾個主要的特性:
1、使用發(fā)布/訂閱消息模式,提供一對多的消息發(fā)布,解除耦合,各終端之間無關
2、對負載內(nèi)容屏蔽的消息傳輸,可以對消息訂閱者所接受到的內(nèi)容有所屏蔽
3、具體有三種消息發(fā)布的服務質(zhì)量(以后細說)
4、小型傳輸,開銷小,固定長度的頭部是 2 字節(jié),協(xié)議交換最小化,以降低網(wǎng)絡流量
5、使用Last Will和Testament特性通知有關各方客戶端異常中斷的機制
應用實現(xiàn)
為了更方便的抓包分析,進行了MQTT協(xié)議的服務端與客戶端的應用實現(xiàn)
運行機制
服務端:通過云端一個服務器程序開啟MQTT服務器(Broker),常見的如EMQ
客戶端:不管是IoT管理應用程序還是IoT設備,都屬性于客戶端程序
訂閱:各客戶端程序如果想要接收到別人發(fā)送過來的數(shù)據(jù),就需要訂閱一個主題(Topic)
發(fā)布:任何客戶端都可以根據(jù)一個主題向服務器發(fā)布消息,服務器會根據(jù)訂立記錄,將消息推送至訂閱了對應主題的客戶端
數(shù)據(jù)傳輸格式
MQTT報文大體上包含三大部分:固定報頭、可變報頭、報文載荷,整體結(jié)構(gòu)如下
固定報頭
第一個字節(jié)中高4位保存了消息的類型信息,包含1-14種類型(5.0版本擴充了第15個:認證交換)
1 CONNECT – 連接服務端
2 CONNACK – 確認連接請求
3 PUBLISH – 發(fā)布消息
4 PUBACK –發(fā)布確認
5 PUBREC – 發(fā)布收到(QoS 2,第一步)
6 PUBREL – 發(fā)布釋放(QoS 2,第二步)
7 PUBCOMP – 發(fā)布完成(QoS 2,第三步)
8 SUBSCRIBE - 訂閱主題
9 SUBACK – 訂閱確認
10 UNSUBSCRIBE –取消訂閱
11 UNSUBACK – 取消訂閱確認
12 PINGREQ – 心跳請求
13 PINGRESP – 心跳響應
14 DISCONNECT – 斷開連接
15 AUTH – 認證交換
可變報頭
報文載荷
報文截獲
利用 WireShark進行報文截獲,以連接請求報文為例:
C#代碼實現(xiàn)
此處以客戶端發(fā)送連接請求為例,完整報文拼接實例如下
static void Main(string[] args) {Console.WriteLine("歡迎關注朝夕教育,我是Jovan");try{string ip = "127.0.0.1";int port = 1883;string username = "admin";string password = "123456";string clientId = "C001";//Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);socketClient.Connect(ip, port);Console.WriteLine(">>> TCP 連接通道已建立");// 建立MQTT連接{// 構(gòu)建MQTT報文Listbytes = new List();bytes.AddRange(new byte[] { 0, 4 });// Protocol Name Lengthbytes.AddRange(Encoding.ASCII.GetBytes("MQTT"));// Protocol Namebytes.Add(4);byte flag = 0;flag |= 128;// 用戶名標記flag |= 64; // 密碼標記flag |= 2; ?// Clean Session 標記bytes.Add(flag);// KeepAlivebyte[] bytesKeepAlive = BitConverter.GetBytes((int)TimeSpan.FromSeconds(100).TotalSeconds);bytes.Add(bytesKeepAlive[1]);bytes.Add(bytesKeepAlive[0]);// ClientIDbyte[] clienIdBytes = Encoding.ASCII.GetBytes(clientId);bytes.Add((byte)(clienIdBytes.Length / 256));bytes.Add((byte)(clienIdBytes.Length % 256));// 長度占兩個字節(jié)bytes.AddRange(clienIdBytes);// UserNamebyte[] usernameBytes = Encoding.ASCII.GetBytes(username);bytes.Add((byte)(usernameBytes.Length / 256));bytes.Add((byte)(usernameBytes.Length % 256));// 長度占兩個字節(jié)bytes.AddRange(usernameBytes);// Passwordbyte[] passwordBytes = Encoding.ASCII.GetBytes(password);bytes.Add((byte)(passwordBytes.Length / 256));bytes.Add((byte)(passwordBytes.Length % 256));// 長度占兩個字節(jié)bytes.AddRange(passwordBytes);byte[] bufferLen = new byte[] { (byte)bytes.Count };MemoryStream memoryStream = new MemoryStream();memoryStream.WriteByte(1 << 4);memoryStream.Write(bufferLen, 0, (int)bufferLen.Length);memoryStream.Write(bytes.ToArray(), 0, (int)bytes.Count);byte[] array = memoryStream.ToArray();memoryStream.Close();socketClient.Send(array);}}catch (Exception ex){Console.WriteLine(ex.Message);}Console.ReadLine(); }總結(jié)
以上是生活随笔為你收集整理的IOT必备之MQTT结构分析,不进来看看?【后附源码】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 老刘在微软Ignite China大会上
- 下一篇: 如何运用并行编程Parallel提升任务