精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

C語言代碼封裝MQTT協議報文,了解MQTT協議通信過程

DS小龍哥-嵌入式技術 ? 來源:DS小龍哥-嵌入式技術 ? 作者:DS小龍哥-嵌入式技 ? 2023-05-17 09:24 ? 次閱讀

【1】MQTT協議介紹

MQTT是一種輕量級的通信協議,適用于物聯網IoT)和低帶寬網絡環境。它基于一種“發布/訂閱”模式,其中設備發送數據(也稱為 “發布”)到經紀人(稱為MQTT代理),這些數據被存儲,并在需要時被轉發給訂閱者。這種方式簡化了網絡管理,允許多個設備在不同的網絡條件下進行通信(包括延遲和帶寬限制),并支持實時數據更新。它是開放的,可免費使用并易于實施。

【2】MQTT協議報文字段介紹

MQTT協議報文由兩部分組成:固定報頭和可變報頭。

固定報頭的格式是統一的,其中包括了報文類型和剩余長度兩個字段。

可變報頭的格式取決于報文類型。

下面是MQTT協議中各個報文類型的可變報頭字段說明。

(1)CONNECT:MQTT連接請求報文

CONNECT報文包括固定報頭和可變報頭兩部分。其中,固定報頭的第一個字節(即報文類型和標志位的組合)為0x10,表示這是一個CONNECT報文。

可變報頭包括了以下字段:

協議名(Protocol Name):用于標識MQTT協議的名稱,固定為字符串"MQTT";

協議級別(Protocol Level):用于標識所使用的MQTT協議的版本號,一般情況下為4;

連接標志(Connect Flags):用于設置各種連接選項,其中包括:

  • 用戶名/密碼(Username/Password):用于對連接進行身份驗證;
  • 清理會話(Clean Session):表示客戶端需要清除服務器上舊的Session信息;
  • 遺囑標志(Will Flag):表示客戶端是否需要在與服務器的連接意外斷開時發送遺囑信息;
  • 遺囑QoS(Will QoS):用于設置遺囑消息的服務質量等級;
  • 遺囑保留(Will Retain):表示遺囑消息是否需要被服務器保留;
  • 用戶名標志(Username Flag):表示客戶端是否需要發送用戶名字段;
  • 密碼標志(Password Flag):表示客戶端是否需要發送密碼字段。

保持連接(Keep Alive):用于設置心跳包的發送間隔時間,以便客戶端和服務器之間保持連接。

(2)CONNACK:MQTT連接響應報文

CONNACK報文包括固定報頭和可變報頭兩部分。其中,固定報頭的第一個字節為0x20,表示這是一個CONNACK報文。

可變報頭包括了以下字段:

  • 連接應答(Connect Acknowledgment):用于表示連接是否成功,一般為0表示成功,其他值表示失??;
  • 保留標志(Reserved Flag):保留字段,必須為0。

(3)PUBLISH:MQTT發布消息報文

PUBLISH報文包括固定報頭和可變報頭兩部分,以及消息體。其中,固定報頭的第一個字節由報文類型和QoS級別組合而成,QoS級別可以為0、1或2。

可變報頭包括了以下字段:

  • 主題名(Topic Name):用于標識消息的主題;
  • 報文標識符(Packet Identifier):用于在QoS級別為1或2時確認消息分發的情況,如果為0則表示QoS級別為0。

消息體包括了要發布的消息內容。

(4)PUBACK:MQTT發布確認報文

PUBACK報文包括固定報頭和可變報頭兩部分。其中,固定報頭的第一個字節為0x40,表示這是一個PUBACK報文。

可變報頭僅包括一個報文標識符(Packet Identifier)字段,用于確認QoS級別為1的發布消息。

(5)PUBREC:MQTT發布接收報文

PUBREC報文包括固定報頭和可變報頭兩部分。其中,固定報頭的第一個字節為0x50,表示這是一個PUBREC報文。

可變報頭僅包括一個報文標識符(Packet Identifier)字段,用于確認QoS級別為2的發布消息。

(6)PUBREL:MQTT發布釋放報文

PUBREL報文包括固定報頭和可變報頭兩部分。其中,固定報頭的第一個字節為0x62,表示這是一個PUBREL報文。

可變報頭僅包括一個報文標識符(Packet Identifier)字段,用于確認QoS級別為2的發布消息。

(7)PUBCOMP:MQTT發布完成報文

PUBCOMP報文包括固定報頭和可變報頭兩部分。其中,固定報頭的第一個字節為0x70,表示這是一個PUBCOMP報文。

可變報頭僅包括一個報文標識符(Packet Identifier)字段,用于確認QoS級別為2的發布消息。

(8)SUBSCRIBE:MQTT訂閱請求報文

SUBSCRIBE報文包括固定報頭和可變報頭兩部分。其中,固定報頭的第一個字節為0x82,表示這是一個SUBSCRIBE報文。

可變報頭包括了以下字段:

  • 報文標識符(Packet Identifier):用于確認訂閱請求的情況;
  • 訂閱主題(Subscription Topic):用于設置訂閱的主題;
  • 服務質量等級(QoS Level):用于設置訂閱請求使用的服務質量等級,可以為0、1或2。

(9)SUBACK:MQTT訂閱確認報文

SUBACK報文包括固定報頭和可變報頭兩部分。其中,固定報頭的第一個字節為0x90,表示這是一個SUBACK報文。

可變報頭包括了以下字段:

  • 報文標識符(Packet Identifier):用于確認訂閱請求的情況;
  • 訂閱確認等級(Subscription Acknowledgment):用于確認訂閱請求的服務質量等級,可以為0、1或2。

(10)UNSUBSCRIBE:MQTT取消訂閱報文

UNSUBSCRIBE報文包括固定報頭和可變報頭兩部分。其中,固定報頭的第一個字節為0xA2,表示這是一個UNSUBSCRIBE報文。

可變報頭包括了以下字段:

  • 報文標識符(Packet Identifier):用于確認取消訂閱請求的情況;
  • 訂閱主題(Subscription Topic):用于設置要取消訂閱的主題。

(11)UNSUBACK:MQTT取消訂閱確認報文

UNSUBACK報文包括固定報頭和可變報頭兩部分。其中,固定報頭的第一個字節為0xB0,表示這是一個UNSUBACK報文。

可變報頭僅包含報文標識符(Packet Identifier)字段,用于確認取消訂閱請求。

(12)PINGREQ:MQTT心跳請求報文

PINGREQ報文包括固定報頭和可變報頭兩部分。其中,固定報頭的第一個字節為0xC0,表示這是一個PINGREQ報文。

PINGREQ報文不包含可變報頭字段。

(13)PINGRESP:MQTT心跳響應報文

PINGRESP報文包括固定報頭和可變報頭兩部分。其中,固定報頭的第一個字節為0xD0,表示這是一個PINGRESP報文。

PINGRESP報文不包含可變報頭字段。

(14)DISCONNECT:MQTT斷開連接報文

DISCONNECT報文包括固定報頭和可變報頭兩部分。其中,固定報頭的第一個字節為0xE0,表示這是一個DISCONNECT報文。

DISCONNECT報文不包含可變報頭字段。

【3】封裝MQTT協議

這是一個使用C語言Linux下建立TCP通信并發送MQTT報文的例子。 根據MQTT報文自己封裝協議。

#include 
#include 
#include 
#include 
#include 
#include 
?
// 定義MQTT報文類型
#define MQTT_CONNECT   0x10
#define MQTT_CONNACK   0x20
#define MQTT_PUBLISH   0x30
#define MQTT_PUBACK   0x40
#define MQTT_SUBSCRIBE  0x80
#define MQTT_SUBACK   0x90
#define MQTT_UNSUBSCRIBE   0xA0
#define MQTT_UNSUBACK  0xB0
#define MQTT_PINGREQ   0xC0
#define MQTT_PINGRESP  0xD0
#define MQTT_DISCONNECT   0xE0
?
// 定義MQTT連接標志
#define MQTT_CONNECT_FLAG_CLEAN   0x02
#define MQTT_CONNECT_FLAG_WILL    0x04
#define MQTT_CONNECT_FLAG_WILL_QOS0 0x00
#define MQTT_CONNECT_FLAG_WILL_QOS1 0x08
#define MQTT_CONNECT_FLAG_WILL_QOS2 0x10
#define MQTT_CONNECT_FLAG_WILL_RETAIN  0x20
#define MQTT_CONNECT_FLAG_PASSWORD  0x40
#define MQTT_CONNECT_FLAG_USERNAME  0x80
?
// 定義MQTT報文結構體
typedef struct mqtt_packet 
{
    unsigned char *data;
    unsigned int length;
}
mqtt_packet_t;
?
// 建立socket連接并返回socket文件描述符
int socket_connect(char *address, int port) 
{
    struct sockaddr_in server_address;
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd == -1) 
    {
        printf("Failed to create socket!n");
        return -1;
    }
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(port);
    if ((inet_pton(AF_INET, address, &server_address.sin_addr)) <= 0) 
?    {
?        printf("Invalid address/ Address not supportedn");
?        return -1;
?    }
?    if (connect(socket_fd, (struct sockaddr *)&server_address, sizeof(server_address)) < 0) 
?    {
?        printf("Connection Failed!n");
?        return -1;
?    }
?    return socket_fd;
?}
?// 打包MQTT連接報文 
?mqtt_packet_t *mqtt_connect(char *client_id, char *username, char *password) 
?{
?    mqtt_packet_t *packet = (mqtt_packet_t *)malloc(sizeof(mqtt_packet_t));
?    unsigned char *data = (unsigned char *)malloc(256);
?    unsigned int length = 0;
?    // 固定報頭 
?    data[length++] = MQTT_CONNECT;
?    // 可變報頭 
?    data[length++] = 0x0C;
?    // 清理會話標志和協議版本號
?    data[length++] = 'M';
?    data[length++] = 'Q';
?    data[length++] = 'T';
?    data[length++] = 'T';
?    data[length++] = 0x04;
?    // 協議版本號 // 連接標志 
?    unsigned char flags = MQTT_CONNECT_FLAG_CLEAN;
?    if (username != NULL) 
?    {
?        flags |= MQTT_CONNECT_FLAG_USERNAME;
?    }
?    if (password != NULL) 
?    {
?        flags |= MQTT_CONNECT_FLAG_PASSWORD;
?    }
?    data[length++] = flags;
?    data[length++] = 0xFF;
?    // 保持連接時間低8位 
?    data[length++] = 0xFF;
?    // 保持連接時間高8位 // 剩余長度 
?    unsigned char remaining_length = length - 1;
?    data[remaining_length++] = (unsigned char)(length - 2);
?    packet->data = data;
    packet->length = length;
    return packet;
}
// 發送MQTT報文 
void mqtt_send(int socket_fd, mqtt_packet_t *packet) 
{
    if (send(socket_fd, packet->data, packet->length, 0) < 0) 
?    {
?        printf("Failed to send message!n");
?    }
?}
?// 接收MQTT報文
?int mqtt_recv(int socket_fd, mqtt_packet_t *packet) 
?{
?    unsigned char header[2];
?    if (recv(socket_fd, header, 2, 0) != 2) 
?    {
?        printf("Failed to receive message header!n");
?        return -1
?    }
?    unsigned int remaining_length = 0;
?    unsigned int multiplier = 1;
?    int i = 1;
?    do 
?    {
?        if (recv(socket_fd, &header[i], 1, 0) != 1) 
?        {
?            printf("Failed to receive remaining_length byte %d!n", i);
?            return -1;
?        }
?        remaining_length += (header[i] & 127) * multiplier;
?        multiplier *= 128;
?        i++;
?    }
?    while ((header[i - 1] & 128) != 0);
?    packet->length = remaining_length + i;
    packet->data = (unsigned char *)malloc(packet->length);
    memcpy(packet->data, header, 2);
    if (recv(socket_fd, packet->data + 2, packet->length - 2, 0) != packet->length - 2) 
    {
        printf("Failed to receive full message!n");
        return -1;
    }
    return 0;
}
?
?
int main(int argc, char *argv[]) 
{
    // 建立 TCP 連接 
    int socket_fd = socket_connect("test.mosquitto.org", 1883);
    if (socket_fd == -1) 
    {
        printf("Failed to connect to MQTT server!n");
        return -1;
    }
    printf("Connected to MQTT server!n");
    // 打包并發送 MQTT 連接報文
    mqtt_packet_t *connect_packet = mqtt_connect("test_client", NULL, NULL);
    mqtt_send(socket_fd, connect_packet);
    printf("Sent MQTT CONNECT packet!n");
    free(connect_packet->data);
    free(connect_packet);
    // 接收 MQTT CONNACK 報文
    mqtt_packet_t *connack_packet = (mqtt_packet_t *)malloc(sizeof(mqtt_packet_t));
    if (mqtt_recv(socket_fd, connack_packet) != 0) 
    {
        printf("Failed to receive MQTT CONNACK packet!n");
        return -1;
    }
    if (connack_packet->data[1] != 0x00) 
    {
        printf("MQTT server rejected connection!n");
        return -1;
    }
    printf("Received MQTT CONNACK packet!n");
    free(connack_packet->data);
    free(connack_packet);
    // 斷開 TCP 連接 close(socket_fd); return 0; 
}
    
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 單片機
    +關注

    關注

    6032

    文章

    44518

    瀏覽量

    633063
  • 通信
    +關注

    關注

    18

    文章

    5972

    瀏覽量

    135860
  • C語言
    +關注

    關注

    180

    文章

    7598

    瀏覽量

    136207
  • 代碼
    +關注

    關注

    30

    文章

    4750

    瀏覽量

    68357
  • MQTT
    +關注

    關注

    5

    文章

    649

    瀏覽量

    22435
收藏 人收藏

    評論

    相關推薦

    如何使用Rust語言和paho-mqtt模塊實現MQTT協議

    MQTT是一種輕量級的消息傳輸協議,它被廣泛應用于物聯網和機器對機器通信領域。Rust是一種安全、高效、并發的編程語言,它的生態系統也在不斷壯大。本教程將介紹如何使用Rust
    的頭像 發表于 09-19 14:41 ?1891次閱讀

    MQTT 協議 開發入門

    在于,可以以極少的代碼和有限的帶寬,為連接遠程設備提供實時可靠的消息服務。作為一種低開銷、低帶寬占用的即時通訊協議,使其在物聯網、小型設備、移動應用等方面有較廣泛的應用。MQTT是一個基于客戶端-服務器
    發表于 11-07 15:51

    MQTT是什么?MQTT協議的特點有哪些

    MQTT是什么?MQTT協議的特點有哪些?MQTT協議有幾種消息發布服務質量???
    發表于 09-29 07:43

    MQTT協議學習過程記錄

    學習mqtt協議(一)介紹1--6步內容第一步 了解全局第二步 確定范圍第三步 定義目標第四步 尋找資源第五步 創建學習計劃第六步 篩選資源總結介紹采用10步學習法學習mqtt
    發表于 01-07 06:32

    MQTT協議的相關資料分享

    前言搞智能家居就不得不說到網絡通信,因為我們需要通過各種終端去控制我們的智能家居設備,所以網絡通信這方面是必備的.而在市面上比較流行的網絡通訊協議就是MQTT
    發表于 01-20 07:11

    MQTT協議常用報文詳解

    STM32 MQTT協議 連接中國移動OneNet服務器 上傳接收數據(二)上一次我們講了MQTT協議的連接報文,這次我們來講一下
    發表于 01-20 06:15

    物聯網的基石-MQTT協議初識

    MQTT 協議 是基于發布/訂閱模式的物聯網通信協議,憑借簡單易實現、支持 QoS、報文小等特點,占據了物聯網協議的半壁江山:原作者:ed
    發表于 09-08 16:03

    MQTT協議采集網關可自定義格式

    語言如Java或C++,以及Modbus RTU協議庫和MQTT協議庫。首先,我們需要通過串口或網絡接口接收Modbus RTU
    發表于 10-09 19:33

    mqtt-v3.1.1版協議

    mqtt-v3.1.1版協議,英文版,時間2014.10.29,物聯網通信協議MQTT
    發表于 10-29 11:22 ?0次下載

    干貨:MQTT協議開發入門

    于 TCP/IP 協議上,由 IBM 在 1999 年發布。 簡述 MQTT 最大優點在于,可以以極少的代碼和有限的帶寬,為連接遠程設備提供實時可靠的消息服務。 作為一種低開銷、低帶寬占用的即時通訊
    的頭像 發表于 10-25 09:16 ?3312次閱讀

    網絡協議棧:MQTT報文格式解析

    在上一篇文章,直接在本地搭建了服務器和客戶端,簡單的實踐了MQTT的用法。而這一篇來解析MQTT報文格式。MQTT報文字段很精簡。但是解
    的頭像 發表于 05-13 14:06 ?5351次閱讀
    網絡<b class='flag-5'>協議</b>棧:<b class='flag-5'>MQTT</b>的<b class='flag-5'>報文</b>格式解析

    Linux應用開發【第十六章】MQTT協議分析應用開發

    文章目錄 16 MQTT協議分析應用開發 16.1 mqtt協議介紹 16.1.1 概述 16.1.2 特點 16.1.3 應用 16.2 mqtt
    的頭像 發表于 12-10 19:32 ?645次閱讀
    Linux應用開發【第十六章】<b class='flag-5'>MQTT</b><b class='flag-5'>協議</b>分析應用開發

    MQTT 協議:機器對機器通信的解決方案?

    MQTT 協議:機器對機器通信的解決方案?
    的頭像 發表于 01-05 09:43 ?809次閱讀

    MQTT 5協議你知道多少?

    MQTT協議是當今世界上最流行、接受度最高的物聯網協議。自推出以來,MQTT協議在各行業應用廣泛。本文帶大家
    的頭像 發表于 02-23 13:14 ?786次閱讀

    MQTT協議簡介及協議原理

    ,因此它具有非常高的可靠性,同時它是基于TCP協議的 模型發布/訂閱主題消息的輕量級協議,也是我們常說的發送與接收數據,下面我們來初步了解一下mqtt相關的名稱與功
    的頭像 發表于 02-28 16:16 ?6936次閱讀
    <b class='flag-5'>MQTT</b><b class='flag-5'>協議</b>簡介及<b class='flag-5'>協議</b>原理