RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C語言代碼封裝MQTT協(xié)議報(bào)文,了解MQTT協(xié)議通信過程

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

【1】MQTT協(xié)議介紹

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

【2】MQTT協(xié)議報(bào)文字段介紹

MQTT協(xié)議報(bào)文由兩部分組成:固定報(bào)頭和可變報(bào)頭。

固定報(bào)頭的格式是統(tǒng)一的,其中包括了報(bào)文類型和剩余長(zhǎng)度兩個(gè)字段。

可變報(bào)頭的格式取決于報(bào)文類型。

下面是MQTT協(xié)議中各個(gè)報(bào)文類型的可變報(bào)頭字段說明。

(1)CONNECT:MQTT連接請(qǐng)求報(bào)文

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

可變報(bào)頭包括了以下字段:

協(xié)議名(Protocol Name):用于標(biāo)識(shí)MQTT協(xié)議的名稱,固定為字符串"MQTT";

協(xié)議級(jí)別(Protocol Level):用于標(biāo)識(shí)所使用的MQTT協(xié)議的版本號(hào),一般情況下為4;

連接標(biāo)志(Connect Flags):用于設(shè)置各種連接選項(xiàng),其中包括:

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

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

(2)CONNACK:MQTT連接響應(yīng)報(bào)文

CONNACK報(bào)文包括固定報(bào)頭和可變報(bào)頭兩部分。其中,固定報(bào)頭的第一個(gè)字節(jié)為0x20,表示這是一個(gè)CONNACK報(bào)文。

可變報(bào)頭包括了以下字段:

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

(3)PUBLISH:MQTT發(fā)布消息報(bào)文

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

可變報(bào)頭包括了以下字段:

  • 主題名(Topic Name):用于標(biāo)識(shí)消息的主題;
  • 報(bào)文標(biāo)識(shí)符(Packet Identifier):用于在QoS級(jí)別為1或2時(shí)確認(rèn)消息分發(fā)的情況,如果為0則表示QoS級(jí)別為0。

消息體包括了要發(fā)布的消息內(nèi)容。

(4)PUBACK:MQTT發(fā)布確認(rèn)報(bào)文

PUBACK報(bào)文包括固定報(bào)頭和可變報(bào)頭兩部分。其中,固定報(bào)頭的第一個(gè)字節(jié)為0x40,表示這是一個(gè)PUBACK報(bào)文。

可變報(bào)頭僅包括一個(gè)報(bào)文標(biāo)識(shí)符(Packet Identifier)字段,用于確認(rèn)QoS級(jí)別為1的發(fā)布消息。

(5)PUBREC:MQTT發(fā)布接收?qǐng)?bào)文

PUBREC報(bào)文包括固定報(bào)頭和可變報(bào)頭兩部分。其中,固定報(bào)頭的第一個(gè)字節(jié)為0x50,表示這是一個(gè)PUBREC報(bào)文。

可變報(bào)頭僅包括一個(gè)報(bào)文標(biāo)識(shí)符(Packet Identifier)字段,用于確認(rèn)QoS級(jí)別為2的發(fā)布消息。

(6)PUBREL:MQTT發(fā)布釋放報(bào)文

PUBREL報(bào)文包括固定報(bào)頭和可變報(bào)頭兩部分。其中,固定報(bào)頭的第一個(gè)字節(jié)為0x62,表示這是一個(gè)PUBREL報(bào)文。

可變報(bào)頭僅包括一個(gè)報(bào)文標(biāo)識(shí)符(Packet Identifier)字段,用于確認(rèn)QoS級(jí)別為2的發(fā)布消息。

(7)PUBCOMP:MQTT發(fā)布完成報(bào)文

PUBCOMP報(bào)文包括固定報(bào)頭和可變報(bào)頭兩部分。其中,固定報(bào)頭的第一個(gè)字節(jié)為0x70,表示這是一個(gè)PUBCOMP報(bào)文。

可變報(bào)頭僅包括一個(gè)報(bào)文標(biāo)識(shí)符(Packet Identifier)字段,用于確認(rèn)QoS級(jí)別為2的發(fā)布消息。

(8)SUBSCRIBE:MQTT訂閱請(qǐng)求報(bào)文

SUBSCRIBE報(bào)文包括固定報(bào)頭和可變報(bào)頭兩部分。其中,固定報(bào)頭的第一個(gè)字節(jié)為0x82,表示這是一個(gè)SUBSCRIBE報(bào)文。

可變報(bào)頭包括了以下字段:

  • 報(bào)文標(biāo)識(shí)符(Packet Identifier):用于確認(rèn)訂閱請(qǐng)求的情況;
  • 訂閱主題(Subscription Topic):用于設(shè)置訂閱的主題;
  • 服務(wù)質(zhì)量等級(jí)(QoS Level):用于設(shè)置訂閱請(qǐng)求使用的服務(wù)質(zhì)量等級(jí),可以為0、1或2。

(9)SUBACK:MQTT訂閱確認(rèn)報(bào)文

SUBACK報(bào)文包括固定報(bào)頭和可變報(bào)頭兩部分。其中,固定報(bào)頭的第一個(gè)字節(jié)為0x90,表示這是一個(gè)SUBACK報(bào)文。

可變報(bào)頭包括了以下字段:

  • 報(bào)文標(biāo)識(shí)符(Packet Identifier):用于確認(rèn)訂閱請(qǐng)求的情況;
  • 訂閱確認(rèn)等級(jí)(Subscription Acknowledgment):用于確認(rèn)訂閱請(qǐng)求的服務(wù)質(zhì)量等級(jí),可以為0、1或2。

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

UNSUBSCRIBE報(bào)文包括固定報(bào)頭和可變報(bào)頭兩部分。其中,固定報(bào)頭的第一個(gè)字節(jié)為0xA2,表示這是一個(gè)UNSUBSCRIBE報(bào)文。

可變報(bào)頭包括了以下字段:

  • 報(bào)文標(biāo)識(shí)符(Packet Identifier):用于確認(rèn)取消訂閱請(qǐng)求的情況;
  • 訂閱主題(Subscription Topic):用于設(shè)置要取消訂閱的主題。

(11)UNSUBACK:MQTT取消訂閱確認(rèn)報(bào)文

UNSUBACK報(bào)文包括固定報(bào)頭和可變報(bào)頭兩部分。其中,固定報(bào)頭的第一個(gè)字節(jié)為0xB0,表示這是一個(gè)UNSUBACK報(bào)文。

可變報(bào)頭僅包含報(bào)文標(biāo)識(shí)符(Packet Identifier)字段,用于確認(rèn)取消訂閱請(qǐng)求。

(12)PINGREQ:MQTT心跳請(qǐng)求報(bào)文

PINGREQ報(bào)文包括固定報(bào)頭和可變報(bào)頭兩部分。其中,固定報(bào)頭的第一個(gè)字節(jié)為0xC0,表示這是一個(gè)PINGREQ報(bào)文。

PINGREQ報(bào)文不包含可變報(bào)頭字段。

(13)PINGRESP:MQTT心跳響應(yīng)報(bào)文

PINGRESP報(bào)文包括固定報(bào)頭和可變報(bào)頭兩部分。其中,固定報(bào)頭的第一個(gè)字節(jié)為0xD0,表示這是一個(gè)PINGRESP報(bào)文。

PINGRESP報(bào)文不包含可變報(bào)頭字段。

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

DISCONNECT報(bào)文包括固定報(bào)頭和可變報(bào)頭兩部分。其中,固定報(bào)頭的第一個(gè)字節(jié)為0xE0,表示這是一個(gè)DISCONNECT報(bào)文。

DISCONNECT報(bào)文不包含可變報(bào)頭字段。

【3】封裝MQTT協(xié)議

這是一個(gè)使用C語言Linux下建立TCP通信并發(fā)送MQTT報(bào)文的例子。 根據(jù)MQTT報(bào)文自己封裝協(xié)議。

#include 
#include 
#include 
#include 
#include 
#include 
?
// 定義MQTT報(bào)文類型
#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連接標(biāo)志
#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報(bào)文結(jié)構(gòu)體
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連接報(bào)文 
?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;
?    // 固定報(bào)頭 
?    data[length++] = MQTT_CONNECT;
?    // 可變報(bào)頭 
?    data[length++] = 0x0C;
?    // 清理會(huì)話標(biāo)志和協(xié)議版本號(hào)
?    data[length++] = 'M';
?    data[length++] = 'Q';
?    data[length++] = 'T';
?    data[length++] = 'T';
?    data[length++] = 0x04;
?    // 協(xié)議版本號(hào) // 連接標(biāo)志 
?    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;
?    // 保持連接時(shí)間低8位 
?    data[length++] = 0xFF;
?    // 保持連接時(shí)間高8位 // 剩余長(zhǎng)度 
?    unsigned char remaining_length = length - 1;
?    data[remaining_length++] = (unsigned char)(length - 2);
?    packet->data = data;
    packet->length = length;
    return packet;
}
// 發(fā)送MQTT報(bào)文 
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報(bào)文
?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");
    // 打包并發(fā)送 MQTT 連接報(bào)文
    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 報(bào)文
    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; 
}
    
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 單片機(jī)
    +關(guān)注

    關(guān)注

    6035

    文章

    44554

    瀏覽量

    634614
  • 通信
    +關(guān)注

    關(guān)注

    18

    文章

    6024

    瀏覽量

    135949
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7604

    瀏覽量

    136683
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4779

    瀏覽量

    68521
  • MQTT
    +關(guān)注

    關(guān)注

    5

    文章

    650

    瀏覽量

    22487
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    百問MQTT協(xié)議分析 - MQTT簡(jiǎn)述及協(xié)議報(bào)文格式組成

    )1字節(jié)固定報(bào)頭,2字節(jié)心跳報(bào)文,報(bào)文結(jié)構(gòu)緊湊 e)消息QoS支持,可靠傳輸保證 16.1.3 應(yīng)用 ?MQTT協(xié)議廣泛應(yīng)用于物聯(lián)網(wǎng)、移動(dòng)互聯(lián)網(wǎng)、智能硬件、車聯(lián)網(wǎng)、電力能源等領(lǐng)域。 a
    發(fā)表于 12-13 09:29

    百問MQTT協(xié)議分析 - 報(bào)文分析①

    ,與3.1.1節(jié)分析的固定報(bào)頭組成分析一致。 16.3.10.2 c語言構(gòu)造mqtt connect報(bào)文 static uint8_t client_id[512] = {\&quo
    發(fā)表于 12-13 09:41

    MQTT是什么?MQTT協(xié)議的特點(diǎn)有哪些

    MQTT是什么?MQTT協(xié)議的特點(diǎn)有哪些?MQTT協(xié)議有幾種消息發(fā)布服務(wù)質(zhì)量啊?
    發(fā)表于 09-29 07:43

    MQTT協(xié)議學(xué)習(xí)過程記錄

    學(xué)習(xí)mqtt協(xié)議(一)介紹1--6步內(nèi)容第一步 了解全局第二步 確定范圍第三步 定義目標(biāo)第四步 尋找資源第五步 創(chuàng)建學(xué)習(xí)計(jì)劃第六步 篩選資源總結(jié)介紹采用10步學(xué)習(xí)法學(xué)習(xí)mqtt
    發(fā)表于 01-07 06:32

    MQTT協(xié)議的相關(guān)資料分享

    前言搞智能家居就不得不說到網(wǎng)絡(luò)通信,因?yàn)槲覀冃枰ㄟ^各種終端去控制我們的智能家居設(shè)備,所以網(wǎng)絡(luò)通信這方面是必備的.而在市面上比較流行的網(wǎng)絡(luò)通訊協(xié)議就是MQTT
    發(fā)表于 01-20 07:11

    MQTT協(xié)議常用報(bào)文詳解

    STM32 MQTT協(xié)議 連接中國(guó)移動(dòng)OneNet服務(wù)器 上傳接收數(shù)據(jù)(二)上一次我們講了MQTT協(xié)議的連接報(bào)文,這次我們來講一下
    發(fā)表于 01-20 06:15

    物聯(lián)網(wǎng)的基石-MQTT協(xié)議初識(shí)

    。MQTT 協(xié)議 是基于發(fā)布/訂閱模式的物聯(lián)網(wǎng)通信協(xié)議,憑借簡(jiǎn)單易實(shí)現(xiàn)、支持 QoS、報(bào)文小等特點(diǎn),占據(jù)了物聯(lián)網(wǎng)協(xié)議的半壁江山:原作者:ed
    發(fā)表于 09-08 16:03

    MQTT協(xié)議采集網(wǎng)關(guān)可自定義格式

    語言如Java或C++,以及Modbus RTU協(xié)議庫和MQTT協(xié)議庫。首先,我們需要通過串口或網(wǎng)絡(luò)接口接收Modbus RTU
    發(fā)表于 10-09 19:33

    mqtt-v3.1.1版協(xié)議

    mqtt-v3.1.1版協(xié)議,英文版,時(shí)間2014.10.29,物聯(lián)網(wǎng)通信協(xié)議MQTT
    發(fā)表于 10-29 11:22 ?0次下載

    干貨:MQTT協(xié)議開發(fā)入門

    于 TCP/IP 協(xié)議上,由 IBM 在 1999 年發(fā)布。 簡(jiǎn)述 MQTT 最大優(yōu)點(diǎn)在于,可以以極少的代碼和有限的帶寬,為連接遠(yuǎn)程設(shè)備提供實(shí)時(shí)可靠的消息服務(wù)。 作為一種低開銷、低帶寬占用的即時(shí)通訊
    的頭像 發(fā)表于 10-25 09:16 ?3329次閱讀

    網(wǎng)絡(luò)協(xié)議棧:MQTT報(bào)文格式解析

    在上一篇文章,直接在本地搭建了服務(wù)器和客戶端,簡(jiǎn)單的實(shí)踐了MQTT的用法。而這一篇來解析MQTT報(bào)文格式。MQTT報(bào)文字段很精簡(jiǎn)。但是解
    的頭像 發(fā)表于 05-13 14:06 ?5452次閱讀
    網(wǎng)絡(luò)<b class='flag-5'>協(xié)議</b>棧:<b class='flag-5'>MQTT</b>的<b class='flag-5'>報(bào)文</b>格式解析

    Linux應(yīng)用開發(fā)【第十六章】MQTT協(xié)議分析應(yīng)用開發(fā)

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

    MQTT 協(xié)議:機(jī)器對(duì)機(jī)器通信的解決方案?

    MQTT 協(xié)議:機(jī)器對(duì)機(jī)器通信的解決方案?
    的頭像 發(fā)表于 01-05 09:43 ?830次閱讀

    MQTT 5協(xié)議你知道多少?

    MQTT協(xié)議是當(dāng)今世界上最流行、接受度最高的物聯(lián)網(wǎng)協(xié)議。自推出以來,MQTT協(xié)議在各行業(yè)應(yīng)用廣泛。本文帶大家
    的頭像 發(fā)表于 02-23 13:14 ?803次閱讀

    MQTT協(xié)議簡(jiǎn)介及協(xié)議原理

    ,因此它具有非常高的可靠性,同時(shí)它是基于TCP協(xié)議的 模型發(fā)布/訂閱主題消息的輕量級(jí)協(xié)議,也是我們常說的發(fā)送與接收數(shù)據(jù),下面我們來初步了解一下mqtt相關(guān)的名稱與功
    的頭像 發(fā)表于 02-28 16:16 ?7015次閱讀
    <b class='flag-5'>MQTT</b><b class='flag-5'>協(xié)議</b>簡(jiǎn)介及<b class='flag-5'>協(xié)議</b>原理
    RM新时代网站-首页