<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    聶永的博客

    記錄工作/學習的點點滴滴。

    MQTT協議筆記之發布流程

    前言

    這次要講到客戶端/服務器的發布消息行為,與PUBLISH相關的消息類型,會在這里看到。

    PUBLISH

    客戶端發布消息經由服務器分發到所有對應的訂閱者那里。一個訂閱者可以訂閱若干個主題(Topic name),但一個PUBLISH消息只能擁有一個主題。

    消息架構一覽:

     Description76543210
    Fixed header/固定頭部
    byte 1   Message Type(3) DUP flag QoS level RETAIN
        0 0 1 1 0 0 1 0
    byte 2 Remaining Length
    Variable header/可變頭部
    Topic name
    byte 1 Length MSB (0) 0 0 0 0 0 0 0 0
    byte 2 Length LSB (3) 0 0 0 0 0 0 1 1
    byte 3 'a' (0x61) 0 1 1 0 0 0 0 1
    byte 4 '/' (0x2F) 0 0 1 0 1 1 1 1
    byte 5 'b' (0x62) 0 1 1 0 0 0 1 0
    Message Identifier
    byte 6 Message ID MSB (0) 0 0 0 0 0 0 0 0
    byte 7 Message ID LSB (10) 0 0 0 0 1 0 1 0
    Playload/消息體
    BLOB,二進制對象形式。二進制具體包含的內容和格式,可有應用程序自身定義。若消息體為空(0長度)也是可能的。

    固定頭部

    DUP flag,設為0,表示當前為第一次發送。

    RETAIN flag,只有在PUBLISH消息中才有效。

    • 1:表示發送的消息需要一直持久保存,不但要發送給當前的訂閱者,并且以后新來的訂閱了此Topic name的訂閱者會馬上得到推送。 備注:新來乍到的訂閱者,只會取出最新的一個RETAIN flag = 1的消息推送,不是所有。
    • 0:僅僅為當前訂閱者推送此消息。

    可變頭部

    Topic name,UTF-8編碼字符串形式,不支持通配符!

    消息體

    一般作為UTF-8編碼寫入接口,但不排除自定義的消息格式。

    空的消息體(zero-length)的PUBLISH消息也可以是合法的。

    當服務器接收到空消息體(zero-length payload)、retain = 1、具有topic name的一個PUBLISH特殊消息,表示同時滿足retain = 1、相同topic name的這兩個特征的被持久化PUBLISH消息,可被刪除。

    Response/響應

    固定頭部QoS level決定了消息中間件針對發布者具體需要響應的內容:

    QoS Level Expected response
    QoS 0 None
    QoS 1 PUBACK
    QoS 2 PUBREC

    備注:僅僅針對發布PUBLISH消息的發布者。

    Actions:

    無論是訂閱者還是服務器接收到PUBLISH消息之后,需要根據QoS level執行不同動作。

    QoS Level Expected Action
    QoS 0 發送到所有感興趣者
    QoS 1 持久化記錄下來,發送到所有感興趣的參與者,返回一個PUBACK消息給發送者
    QoS 2 持久化記錄下來,暫時不發送所有感興趣的參與者,返回一個PUBREC消息給發送者

    如果服務器收到PUBLISH消息,參與者指的是訂閱者。如果訂閱者收到PUBLISH消息,參與者就是服務器。 需要注意:

    1. 發布者發布的PUBLISH消息發送到服務器,在payload/消息體處可能夾帶有私貨,可能含有自定義的數據 格式
    2. 若兼容MQTT客戶端,經由服務器分發到所有對應訂閱者處只能是規規矩矩的PUBLISH消息,并且固定頭部的RETAIN標志不能被設置成有效值1

    授權

    未經授權的發布者提交的PUBLISH消息,服務器會忽略掉,客戶端不會被通知。

    PUBACK

    作為訂閱者/服務器接收(QoS level = 1)PUBLISH消息之后對發送者的響應,整個消息不復雜。

     Description76543210
    Fixed header/固定頭部
    byte 1   Message type (4) DUP flag QoS flags RETAIN
        0 1 0 0 x x x x
    byte 2   Remaining Length (2)
        0 0 0 0 0 0 1 0
    Variable header/可變頭部
    Message Identifier
    byte 1 Message ID MSB (0) 0 0 0 0 0 0 0 0
    byte 2 Message ID LSB (10) 0 0 0 0 1 0 1 0

    雖沒有消息體,但可變頭部附加一個16位的無符號short類型。

    PUBREC

    字面意思為Assured publish received,作為訂閱者/服務器對QoS level = 2的發布PUBLISH消息的發送方的響應,確認已經收到,為QoS level = 2消息流的第二個消息。 和PUBACK相比,除了消息類型不同外,其它都是一樣。

     Description76543210
    Fixed header/固定頭部
    byte 1   Message type (5) DUP flag QoS flags RETAIN
        0 1 0 1 x x x x
    byte 2   Remaining Length (2)
        0 0 0 0 0 0 1 0
    Variable header/可變頭部
    Message Identifier
    byte 1 Message ID MSB (0) 0 0 0 0 0 0 0 0
    byte 2 Message ID LSB (10) 0 0 0 0 1 0 1 0

    無論是訂閱者還是服務器,在消費PUBREC消息之后需要發送一個PUBREL消息給發送者(和PUBREC具有同樣的消息ID),確認已收到。

    PUBREL

    Qos level = 2的協議流的第三個消息,有PUBLISH消息的發布者發送,參與方接收。完整示范如下:

     Description76543210
    Fixed header/固定頭部
    byte 1   Message type (6) DUP flag QoS flags RETAIN
        0 1 1 0 0 0 1 x
    byte 2   Remaining Length (2)
        0 0 0 0 0 0 1 0
    Variable header/可變頭部
    Message Identifier
    byte 1 Message ID MSB (0) 0 0 0 0 0 0 0 0
    byte 2 Message ID LSB (10) 0 0 0 0 1 0 1 0

    QoS level 1,PUBREL消息要求如此。

    DUP flag 為0,表示消息第一次被發送。

    毫無疑問,剩余長度為2個byte長度。

    可變頭部中,消息ID和發布者接收到的PUBREC所包含的消息ID是一致的。

    動作:

    1. 服務器接收到發布者(a)的PUBREL消息,此時服務器讓發布者(a)剛才發布PUBLISH消息可用,發送此PUBLISH消息給所有訂閱此主題的訂閱者,然后發送PUBCOMP消息給發布者(a)
    2. 可變頭部包含消息ID和服務器接收的PUBREL消息ID是一致的。 一個訂閱者接收到PUBREL消息,訂閱者使PUBLISH消息可用,然后反饋一個PUBCOMP消息給服務器

    PUBCOMP

    作為QoS level = 2消息流第四個,也是最后一個消息,由收到PUBREL的一方向另一方做出的響應消息。

    完整的消息一覽,和PUBREL一致,除了消息類型。

     Description76543210
    Fixed header/固定頭部
    byte 1   Message type (7) DUP flag QoS flags RETAIN
        0 1 1 1 x x x x
    byte 2   Remaining Length (2)
        0 0 0 0 0 0 1 0
    Variable header/可變頭部
    Message Identifier
    byte 1 Message ID MSB (0) 0 0 0 0 0 0 0 0
    byte 2 Message ID LSB (10) 0 0 0 0 1 0 1 0

    當客戶端接收一個PUBCOMP消息時,客戶端摒棄原來的消息,因為它已經成功發送消息到服務器。

    小結

    消息的發布和確認等一些流程,主要是跟消息發布者所設定的QoS level有關;稍加整理,繪制了下面一張圖,理解起來可能會更清晰些:

    Publish流程圖

    上圖針對的是客戶端發布消息到服務器端的方向。

    為了確保消息已經成功傳遞過去,只有收到了確認,才會讓人特別放心。

    在QoS level = 2時,通信雙方都需要知道各自的確認流程以及所處階段等,交互很多,數據量大的情況下,可能會造成數據線路傳遞擁塞。服務器選擇QoS = 0/1,大部分情況都是可以應對的。 比如重要消息,就要確保對方都要收到,然后彼此確認,OK,這個消息是真實、有效的。

    無論Qos level為0、1,還是2,服務器(具備所有條件都滿足之后)總要把收到的具體內容和topic組裝成一個新的PUBLISH Message(也不一定要重新構造,但要求推送的PUBLISH消息,一定要具有明確的主題和內容,RETAIN標志不能設置為1)推送到所有感興趣的訂閱者。

    嗯,消息的發布來源別忘記還有可能來自CONNECT消息中的Will Topic和Will Message,若是設置了Will flag標記的話。

    posted on 2014-02-10 23:42 nieyong 閱讀(17362) 評論(5)  編輯  收藏 所屬分類: MQTT

    評論

    # re: MQTT協議筆記之發布流程 2014-02-11 08:14 鵬達鎖業

    期待博主更新文章。。。加油
      回復  更多評論   

    # re: MQTT協議筆記之發布流程[未登錄] 2015-10-26 16:56 123

    請問,在服務器端,用代理轉發的方式。是一個SUB訂閱多個訂閱號(多個設備的ID)->myaql 方式合理;還是實現多線程SUB,每一個線程的SUB訂閱一個ID在同步到mysql的方式合理。  回復  更多評論   

    # re: MQTT協議筆記之發布流程 2016-12-27 09:00 Haven

    博主牛人呀,有一個QoS2的問題請教,為什么QoS2需要4次包,2次不就可以了嗎?還望回復。  回復  更多評論   

    # re: MQTT協議筆記之發布流程 2017-01-05 15:20 nieyong

    @Haven

    兄弟,針對QoS2,為了便于說明,我們先假設一個方向,Server -> Client:

    ----PUBLISH--->
    <----PUBREC----
    ----PUBREL---->
    <----PUBCOMP---

    1. Server發送PUBLISH消息到Client,Client接收之后需要確認收到嘛,就返回PUBREC吧;但此時Client僅僅是把數據發送出去了而已,至于Server端收不收到那就不得而知
    2. Server接收ClientPUBREC消息之后,需要回一個PUBREL消息告訴Client自己收到啦,同樣道理也僅僅只是發送出去,Client是不是能收到的這個響應,心里面也沒譜呀
    3. Client收到來自Server的PUBREL之后,就非常明白自己針對PUBLISH消息做出的PUBREC響應消息在Server端是已經收到啦,但是需要告訴Server,自己收到它的再三確認啦
    4. Server端此時等待Client上報PUBCOMP消息,一旦接收到之后,表示針對某個消息雙方都再三確認了,這事就沒有問題啦

    其核心所設定網絡是不靠譜的,任何一次發送數據到對端,都有可能因收不到(比如發送之后,某一端斷網啦,或中間路由設備因為容量滿了拋棄啦)。

    好比雙發約定一件事:

    Server - 我給你說說這件事....
    Client - 我同意了你這樣做。
    Server - 你確定你同意了?
    Client - 是的,我同意了。
    Server - OK,那這事就這么定了,我知道該怎么做啦。  回復  更多評論   

    # re: MQTT協議筆記之發布流程 2017-01-10 13:03 Haven

    @nieyong
    謝謝兄弟的回復,

    其實我還是覺得兩次就可以搞定了。同樣以Server -> Client為例

    1. Server發送PUBLISH消息到Client,Client接收之后需要確認收到嘛,就返回PUBREC吧;但此時Client僅僅是把數據發送出去了而已,至于Server端收不收到那就不得而知.
    2. Server可能收到了PUBREC,也可能沒有收到
    a. Server收到了PUBREC, 這時候就表示Client收到消息了,表示成功遞送消息了。
    b. Server沒有收到PUBREC,等待一定時間后,重發PUBLISH即可。

    在1中,Client收到PUBLISH后就把數據保存在數據庫中,如果收到重復PUBLISH重數據庫就可以知道是重復數據。
    在2中,超時就重傳PUBLISH即可。
    感覺這樣兩步完全滿足QoS2了呀!!


    其實我在設計一套私有IM協議,用于自己的App中,希望能加你QQ探討一下MQTT的QoS2問題。
    我的QQ:357545146  回復  更多評論   

    公告

    所有文章皆為原創,若轉載請標明出處,謝謝~

    新浪微博,歡迎關注:

    導航

    <2016年12月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    統計

    常用鏈接

    留言簿(58)

    隨筆分類(130)

    隨筆檔案(151)

    個人收藏

    最新隨筆

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 麻豆亚洲av熟女国产一区二| 久久久久亚洲精品成人网小说 | 亚洲一区二区三区日本久久九| 久久久精品视频免费观看| 免费人成视频在线观看视频| 美女啪啪网站又黄又免费| www国产亚洲精品久久久日本| 青娱乐在线视频免费观看| 相泽亚洲一区中文字幕| 免费人成毛片动漫在线播放 | 日本免费人成黄页在线观看视频 | 西西大胆无码视频免费| 最新亚洲春色Av无码专区| 全免费a级毛片免费看无码| 国产天堂亚洲国产碰碰| 色噜噜AV亚洲色一区二区| 无码午夜成人1000部免费视频| 夜夜亚洲天天久久| 一个人看的www在线观看免费| 亚洲精品亚洲人成在线| 免费一级毛片一级毛片aa| 国产日韩在线视频免费播放| 久久亚洲精品视频| 中文字幕无码免费久久99| 麻豆安全免费网址入口| 亚洲AV无码乱码国产麻豆| 国产精品色拉拉免费看| 污污视频免费观看网站| 色拍自拍亚洲综合图区| 毛片免费在线播放| 国产精品无码免费专区午夜 | 亚洲女同成人AⅤ人片在线观看| 久久青草91免费观看| 亚洲愉拍一区二区三区| 亚洲人成中文字幕在线观看| 麻豆国产精品免费视频| 免费国产在线精品一区| 亚洲天堂一区在线| 激情97综合亚洲色婷婷五| 免费中文熟妇在线影片 | 国产99精品一区二区三区免费|