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

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

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

    聶永的博客

    記錄工作/學(xué)習(xí)的點(diǎn)點(diǎn)滴滴。

    MQTT協(xié)議筆記之發(fā)布流程

    前言

    這次要講到客戶(hù)端/服務(wù)器的發(fā)布消息行為,與PUBLISH相關(guān)的消息類(lèi)型,會(huì)在這里看到。

    PUBLISH

    客戶(hù)端發(fā)布消息經(jīng)由服務(wù)器分發(fā)到所有對(duì)應(yīng)的訂閱者那里。一個(gè)訂閱者可以訂閱若干個(gè)主題(Topic name),但一個(gè)PUBLISH消息只能擁有一個(gè)主題。

    消息架構(gòu)一覽:

     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,二進(jìn)制對(duì)象形式。二進(jìn)制具體包含的內(nèi)容和格式,可有應(yīng)用程序自身定義。若消息體為空(0長(zhǎng)度)也是可能的。

    固定頭部

    DUP flag,設(shè)為0,表示當(dāng)前為第一次發(fā)送。

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

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

    可變頭部

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

    消息體

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

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

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

    Response/響應(yīng)

    固定頭部QoS level決定了消息中間件針對(duì)發(fā)布者具體需要響應(yīng)的內(nèi)容:

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

    備注:僅僅針對(duì)發(fā)布PUBLISH消息的發(fā)布者。

    Actions:

    無(wú)論是訂閱者還是服務(wù)器接收到PUBLISH消息之后,需要根據(jù)QoS level執(zhí)行不同動(dòng)作。

    QoS Level Expected Action
    QoS 0 發(fā)送到所有感興趣者
    QoS 1 持久化記錄下來(lái),發(fā)送到所有感興趣的參與者,返回一個(gè)PUBACK消息給發(fā)送者
    QoS 2 持久化記錄下來(lái),暫時(shí)不發(fā)送所有感興趣的參與者,返回一個(gè)PUBREC消息給發(fā)送者

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

    1. 發(fā)布者發(fā)布的PUBLISH消息發(fā)送到服務(wù)器,在payload/消息體處可能夾帶有私貨,可能含有自定義的數(shù)據(jù) 格式
    2. 若兼容MQTT客戶(hù)端,經(jīng)由服務(wù)器分發(fā)到所有對(duì)應(yīng)訂閱者處只能是規(guī)規(guī)矩矩的PUBLISH消息,并且固定頭部的RETAIN標(biāo)志不能被設(shè)置成有效值1

    授權(quán)

    未經(jīng)授權(quán)的發(fā)布者提交的PUBLISH消息,服務(wù)器會(huì)忽略掉,客戶(hù)端不會(huì)被通知。

    PUBACK

    作為訂閱者/服務(wù)器接收(QoS level = 1)PUBLISH消息之后對(duì)發(fā)送者的響應(yīng),整個(gè)消息不復(fù)雜。

     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

    雖沒(méi)有消息體,但可變頭部附加一個(gè)16位的無(wú)符號(hào)short類(lèi)型。

    PUBREC

    字面意思為Assured publish received,作為訂閱者/服務(wù)器對(duì)QoS level = 2的發(fā)布PUBLISH消息的發(fā)送方的響應(yīng),確認(rèn)已經(jīng)收到,為QoS level = 2消息流的第二個(gè)消息。 和PUBACK相比,除了消息類(lèi)型不同外,其它都是一樣。

     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

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

    PUBREL

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

     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,表示消息第一次被發(fā)送。

    毫無(wú)疑問(wèn),剩余長(zhǎng)度為2個(gè)byte長(zhǎng)度。

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

    動(dòng)作:

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

    PUBCOMP

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

    完整的消息一覽,和PUBREL一致,除了消息類(lèi)型。

     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

    當(dāng)客戶(hù)端接收一個(gè)PUBCOMP消息時(shí),客戶(hù)端摒棄原來(lái)的消息,因?yàn)樗呀?jīng)成功發(fā)送消息到服務(wù)器。

    小結(jié)

    消息的發(fā)布和確認(rèn)等一些流程,主要是跟消息發(fā)布者所設(shè)定的QoS level有關(guān);稍加整理,繪制了下面一張圖,理解起來(lái)可能會(huì)更清晰些:

    Publish流程圖

    上圖針對(duì)的是客戶(hù)端發(fā)布消息到服務(wù)器端的方向。

    為了確保消息已經(jīng)成功傳遞過(guò)去,只有收到了確認(rèn),才會(huì)讓人特別放心。

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

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

    嗯,消息的發(fā)布來(lái)源別忘記還有可能來(lái)自CONNECT消息中的Will Topic和Will Message,若是設(shè)置了Will flag標(biāo)記的話(huà)。

    posted on 2014-02-10 23:42 nieyong 閱讀(17363) 評(píng)論(5)  編輯  收藏 所屬分類(lèi): MQTT

    評(píng)論

    # re: MQTT協(xié)議筆記之發(fā)布流程 2014-02-11 08:14 鵬達(dá)鎖業(yè)

    期待博主更新文章。。。加油
      回復(fù)  更多評(píng)論   

    # re: MQTT協(xié)議筆記之發(fā)布流程[未登錄](méi) 2015-10-26 16:56 123

    請(qǐng)問(wèn),在服務(wù)器端,用代理轉(zhuǎn)發(fā)的方式。是一個(gè)SUB訂閱多個(gè)訂閱號(hào)(多個(gè)設(shè)備的ID)->myaql 方式合理;還是實(shí)現(xiàn)多線(xiàn)程SUB,每一個(gè)線(xiàn)程的SUB訂閱一個(gè)ID在同步到mysql的方式合理。  回復(fù)  更多評(píng)論   

    # re: MQTT協(xié)議筆記之發(fā)布流程 2016-12-27 09:00 Haven

    博主牛人呀,有一個(gè)QoS2的問(wèn)題請(qǐng)教,為什么QoS2需要4次包,2次不就可以了嗎?還望回復(fù)。  回復(fù)  更多評(píng)論   

    # re: MQTT協(xié)議筆記之發(fā)布流程 2017-01-05 15:20 nieyong

    @Haven

    兄弟,針對(duì)QoS2,為了便于說(shuō)明,我們先假設(shè)一個(gè)方向,Server -> Client:

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

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

    其核心所設(shè)定網(wǎng)絡(luò)是不靠譜的,任何一次發(fā)送數(shù)據(jù)到對(duì)端,都有可能因收不到(比如發(fā)送之后,某一端斷網(wǎng)啦,或中間路由設(shè)備因?yàn)槿萘繚M(mǎn)了拋棄啦)。

    好比雙發(fā)約定一件事:

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

    # re: MQTT協(xié)議筆記之發(fā)布流程 2017-01-10 13:03 Haven

    @nieyong
    謝謝兄弟的回復(fù),

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

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

    在1中,Client收到PUBLISH后就把數(shù)據(jù)保存在數(shù)據(jù)庫(kù)中,如果收到重復(fù)PUBLISH重?cái)?shù)據(jù)庫(kù)就可以知道是重復(fù)數(shù)據(jù)。
    在2中,超時(shí)就重傳PUBLISH即可。
    感覺(jué)這樣兩步完全滿(mǎn)足QoS2了呀!!


    其實(shí)我在設(shè)計(jì)一套私有IM協(xié)議,用于自己的App中,希望能加你QQ探討一下MQTT的QoS2問(wèn)題。
    我的QQ:357545146  回復(fù)  更多評(píng)論   

    公告

    所有文章皆為原創(chuàng),若轉(zhuǎn)載請(qǐng)標(biāo)明出處,謝謝~

    新浪微博,歡迎關(guān)注:

    導(dǎo)航

    <2017年1月>
    25262728293031
    1234567
    891011121314
    15161718192021
    22232425262728
    2930311234

    統(tǒng)計(jì)

    常用鏈接

    留言簿(58)

    隨筆分類(lèi)(130)

    隨筆檔案(151)

    個(gè)人收藏

    最新隨筆

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 无码精品人妻一区二区三区免费| 精品日韩99亚洲的在线发布| 免费国产在线精品一区| 国产桃色在线成免费视频| 91亚洲性爱在线视频| 黄色免费网站网址| 亚洲第一男人天堂| 日本免费v片一二三区| 亚洲日韩国产欧美一区二区三区| 久久久久久免费视频| 亚洲综合色区中文字幕| 日韩一区二区a片免费观看 | 三上悠亚电影全集免费| 亚洲人色婷婷成人网站在线观看 | 精品免费久久久久国产一区| 亚洲午夜久久久影院| a毛片免费播放全部完整| 亚洲人成网站影音先锋播放| 国产黄色免费网站| 亚洲精品第一国产综合亚AV| 国产gav成人免费播放视频| 一级毛片免费观看不收费| 亚洲精品成人片在线播放| 免费无码成人AV在线播放不卡| 亚洲免费福利视频| 国产无遮挡吃胸膜奶免费看| 又大又硬又粗又黄的视频免费看 | 在线观看人成视频免费无遮挡| 亚洲av无码成h人动漫无遮挡 | 亚洲国产综合专区电影在线| 国产精品色拉拉免费看| 亚洲爆乳AAA无码专区| 亚洲中文字幕久久精品无码APP| 中文字幕视频免费| 亚洲AV第一成肉网| 中文字幕精品亚洲无线码一区应用| 久久成人免费电影| 亚洲爆乳成av人在线视菜奈实 | 免费能直接在线观看黄的视频| 亚洲av午夜国产精品无码中文字| 亚洲综合精品香蕉久久网|