日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

MQTT Qos详解(一)

發布時間:2023/12/18 c/c++ 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MQTT Qos详解(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文基于標準MQTT討論,不適合其他對MQTT機制做了修改的非標準MQTT協議。

?

MQTT設計了一套保證消息穩定傳輸的機制,包括消息應答、存儲和重傳。在這套機制下,提供了三種不同層次QoS(Quality of Service):

  • QoS0,發送就不管了,最多一次;
  • QoS1,發送之后依賴MQTT規范,是否啟動重傳消息,所以至少一次;
  • QoS2,發送之后依賴MQTT消息機制,確保只有一次。

QoS 是消息的發送方(Sender)和接受方(Receiver)之間達成的一個協議:(MQTT不是端到端的通信)

  • QoS0 代表,Sender 發送的一條消息,Receiver 最多能收到一次,也就是說 Sender 盡力向 Receiver 發送消息,如果發送失敗,也就算了;這是完全依賴TCP重傳機制,如果網絡不好,TCP的重傳也不是100%可靠,加上MQTT是Publisher 發出去的消息是依賴代理服務器完成轉發,所以消息最多一次。
  • QoS1 代表,Sender 發送的一條消息,Receiver 至少能收到一次,也就是說 Sender 向 Receiver 發送消息,如果發送之后沒有收到對應的PUBACK,就會繼續重試,直到發送者Sender 接收到 Receiver 發送的 PUBACK 為止,因為重傳的原因,Receiver 有可能會收到重復的消息;
  • QoS2 代表,Sender 發送的一條消息,Receiver 確保能收到而且只收到一次,也就是說 Sender 盡力向 Receiver 發送消息,如果發送失敗,會繼續重試,直到 Receiver 收到消息為止,同時保證 Receiver 不會因為消息重傳而收到重復的消息。(個人理解這一點有點像TCP三次握手的交互過程)
  • 下面討論Qos不降級的情況,即訂閱者與發布者的Qos等級相同。

    ?

    Qos 0的交互流程:

    ?

  • 消息的分發依賴于底層網絡的能力。接收者不會發送響應,發送者也不會重試。消息可能送達一次也可能根本沒送達。消息從Publisher發送給代理服務broker,或者broker發送給Subscriher,都可能會丟失。
  • 注意:對于QoS 0的消息, DUP標志必須設置為0?

    ?

    Qos 1的交互流程:

    ?

    只有當QoS等級是1或2時, 報文標識符( Packet Identifier) 字段才能出現在PUBLISH報文中。下面是MQTT Qos的補充說明:

    [MQTT-4.3.2-1] 對于QoS 1的分發協議, 發送者

    • 每次發送新的應用消息都必須分配一個未使用的報文標識符。
    • MUST send a PUBLISH Packet containing this Packet Identifier with QoS=1,DUP=0。
    • 發送的PUBLISH報文必須包含報文標識符且QoS等于1,DUP等于0。
    • 必須將這個PUBLISH報文看作是 未確認的 , 直到從接收者那收到對應的PUBACK報文。 4.4節有一個關于未確認消息的討論。

    [MQTT-4.3.2-2] 對于QoS 1的分發協議, 接收者

    • 響應的PUBACK報文必須包含一個報文標識符,這個標識符來自接收到的、已經接受所有權的PUBLISH報文。
    • 發送了PUBACK報文之后,接收者必須將任何包含相同報文標識符的入站PUBLISH報文,當作一個新的消息, 并忽略它的DUP標志的值。
  • Sender 向 Receiver 發送一個帶有消息數據的 PUBLISH 包, 并在本地保存這個 PUBLISH 包。
  • Receiver 收到 PUBLISH 包以后,向 Sender 發送一個 PUBACK 數據包,PUBACK 數據包沒有消息體(Payload),在可變頭中(Variable header)中有一個包標識(Packet Identifier),和它收到的 PUBLISH 包中的報文標識符(Packet Identifier) 一致。
  • Sender 收到 PUBACK 之后,根據 PUBACK 包中的 Packet Identifier 找到本地保存的 PUBLISH 包,然后丟棄掉,一次消息的發送完成。
  • 如果 Sender 在一段時間內沒有收到 PUBLISH 包對應的 PUBACK,它將該 PUBLISH 包的 DUP 標識設為 1(代表是重新發送的 PUBLISH 包),然后重新發送該 PUBLISH 包。重復這個流程,直到收到 PUBACK,然后執行第 3 步。
  • 注意:Qos 1代理服務器是不會進行去重的,只要發布者或者代理服務器沒有收到PUBACK,就認為主題消息沒有發送成功進入重發,代理服務器或者訂閱者,不會根據dup的值進行去重。

    ? ? ? ? 換句話說,代理服務器(broker)或者訂閱者(Subscriber)在發送PUBACK報文時,(Publisher 者)發布消息主題的程序或者代理服務器(broker)的程序,已經對PUBACK報文做了判斷,那么還是會重發該主題消息,并且dup標志位會+1,這樣訂閱者或者代理服務器就會收到多份重復的消息。并且不會去重!

    ?

    Qos 2的交互流程:

    ?

    只有當QoS等級是1或2時, 報文標識符( Packet Identifier) 字段才能出現在PUBLISH報文中,另外QoS 2在消息頭有Message ID。下面是補充說明

    [MQTT-4.3.3-1] 對于QoS 2的分發協議, 發送者

    1、必須給要發送的新應用消息分配一個未使用的報文標識符。

    • MUST send a PUBLISH packet containing this Packet Identifier with QoS=2,DUP=0。

    2、發送的PUBLISH報文必須包含報文標識符且報文的QoS等于2,DUP等于0。

    • 必須將這個PUBLISH報文看作是 未確認的 , 直到從接收者那收到對應的PUBREC報文。 4.4節有一個關于未確認消息的討論。

    • 收到PUBREC報文后必須發送一個PUBREL報文。 PUBREL報文必須包含與原始PUBLISH報文相同的報文標識符。

    • 必須將這個PUBREL報文看作是 未確認的 , 直到從接收者那收到對應的PUBCOMP報文。

    • 一旦發送了對應的PUBREL報文就不能重發這個PUBLISH報文。

    [MQTT-4.3.3-2] 對于QoS 2的分發協議, 接收者

    • 響應的PUBREC報文必須包含報文標識符, 這個標識符來自接收到的、 已經接受所有權的PUBLISH報文。
    • 在收到對應的PUBREL報文之前, 接收者必須發送PUBREC報文確認任何后續的具有相同標識符的PUBLISH報文。 在這種情況下, 它不能重復分發消息給任何后續的接收者。
    • 響應PUBREL報文的PUBCOMP報文必須包含與PUBREL報文相同的標識符。

    ? ? ? ? 發送PUBCOMP報文之后, 接收者必須將包含相同報文標識符的任何后續PUBLISH報文當作一個新的發布。

  • Sender 發送 QoS 為 2 的 PUBLISH 數據包,數據包包含報文標識符:Packet Identifier ,并在本地保存該 PUBLISH 包;
  • Receiver (代理服務器或者訂閱者)收到 PUBLISH 數據包以后,在本地保存 PUBLISH 包,并回復 Sender 一個 PUBREC 數據包,PUBREC 數據包可變頭中的 報文標識符(Packet Identifier)?與 Sender 發送的報文標識符(Packet Identifier)一致,但是沒有消息體(Payload);
  • 當 Sender 收到 PUBREC,它就可以安全地丟棄掉初始發送的PUBLISH包,同時保存該 PUBREC 數據包,同時回復 Receiver 一個 PUBREL 數據包,PUBREL 數據包可變頭中的報文標識符(Packet Identifier)保持不變,同樣沒有消息體(Payload);
  • 如果 Sender 在一定時間內沒有收到 PUBREC,它會把 PUBLISH 包的重發標志位 DUP 標識設為 1,重新發送該 PUBLISH 數據包(Payload);(在第三步和第四步之間是可能存在消息重傳的)
  • 當 Receiver 收到 PUBREL 數據包,它可以丟棄掉保存的 PUBLISH 包,并回復 Sender 一個 PUBCOMP 數據包,PUBCOMP 數據包可變頭中的報文標識符(Packet Identifier)保持不變,沒有消息體(Payload);
  • 當 Sender 收到 PUBCOMP 包,那么它認為數據包傳輸已完成,它會丟棄掉對應的 PUBREC 包。如果 Sender 在一定時間內沒有收到 PUBCOMP 包,它會重新發送 PUBREL 數據包。
  • 注意:

  • 1.Qos 2代理服務器是不會進行去重的,只要發布者或者代理服務器,沒有收到PUBREC,就認為主題消息沒有發送成功進入重發,代理服務器或者訂閱者,不會根據dup的值進行去重。這一步會有去重,保證收到主題消息的唯一性。
  • 發送者或者代理服務器,收到PUBREC,就認為主題消息已經發送出去,不會進行重復發送;至于訂閱者,MQTT會控制顯示消息,如果收到了PUBREL就認為消息已經收到,只需要在發送PUBCOMP,完成MQTT Qos 2 的交互流程。
  • 總結:

    在Qos 1 情況下,如果PUBACK超時或者發送失敗,就會重傳消息;

    在Qos 2情況下,在沒有收到PUBREC之前,也是有消息重傳的可能,但是在接收到PUBREC報文之后,主題消息被刪除,這樣就不會對下面的交互過程產生干擾,消息在這一步之后,只能重傳PUBREC、PUBREL報文。

    總結

    以上是生活随笔為你收集整理的MQTT Qos详解(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。