0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[MQTT] Subscribeについて / Suback

Last updated at Posted at 2025-12-04

はじめに

Subscribeは「このトピックフィルターとマッチするパケットが来たら、私に送信してください!」という宣言です。本記事では構造を確認したあとに実際にSubscribeのパケットを確認してみます。

構造

Fixed Header

サブスクライブパケットのControl Typeは8(0b1000)です。QoSはSubackを返すことが必須であるため、必ず1です。

Variable header

Variable headerにはPacket IDが入ります。Subackはこの値を引用します。

Payload

ペイロードにはトピックフィルターとそれに続いてQoSが入ります。トピックフィルターとQoSのペアは連ねることで複数組のトピックフィルターを一度にサブスクライブすることができます。

  • Topic Filter(UTF-8)
  • それに続く QoS(1 バイト)

Subscribe時の動作

 クライアントからのSubscribeに対してサーバ(ブローカー)はSubackを必ず1つ返さなければなりません。複数のTopic Filterを含んでいる場合は、Topic Filterに対応するReturn Codeを含みます。(Subackに関しては後述)
 トピックフィルターに付随するQoSは、そのトピックフィルターに付与される"許容する最大の"QoSです。つまり、実際のQoSは

min(Publishで指定したQoS, Subscribeで指定したQoS)

です。サーバはSubscribeのQoS要求に応じてPublishで指定したQoSをダウングレードして配信します

Suback

Fixed header

SubackのControl Typeは0b1001です。

Variable header

SubackのVariable headerには対応するSubscribeのPacketIDと同じPacketIDが入ります。

Payload

SubackのPayloadにはReturn Codeが入ります。Subscribeで指定された場合にはSubscribeで指定された順番どおりにReturn Codeを返します。

Return Codeは

  • 0x00 Success 最大QoS0
  • 0x01 Success 最大QoS1
  • 0x02 Success 最大QoS2
  • 0x80 Failure
    です。

実験

サブスクライブするだけのコードを実行してWiresharkで見てみましょう
下記コードは複数トピックをそれぞれ異なるQoSでサブスクライブするクライアントコードです。1日目のコードを改造します。サーバ側は変更ありません。

サーバのGoコード

import paho.mqtt.client as mqtt
import threading
import time

BROKER = "localhost"

# ★ 複数フィルター + QoS 別々
SUB_TOPICS = [
    ("test/topic", 0),        # QoS 0
    ("home/living/temp", 1),  # QoS 1
    ("device/+/status", 2),   # QoS 2
]

# ======================
# Subscriber
# ======================
def on_message(client, userdata, msg):
    print(f"[受信] {msg.topic}: {msg.payload.decode()}")

def subscriber():
    sub = mqtt.Client(
        client_id="sub-client",
        callback_api_version=mqtt.CallbackAPIVersion.VERSION2,
        protocol=mqtt.MQTTv311  # ★ MQTT 3.1.1
    )
    sub.on_message = on_message
    sub.connect(BROKER, 1883, 60)

    # ★ 複数トピックを QoS 別々で購読
    sub.subscribe(SUB_TOPICS)

    sub.loop_forever()

# ======================
# メイン処理(Subscriber 起動のみ)
# ======================
if __name__ == "__main__":
    t = threading.Thread(target=subscriber, daemon=True)
    t.start()

    # Subscriber が走り続ける
    while True:
        time.sleep(1)

SubscribeのあとにSubackが返っています。また、paho-mqttはConnect Ackを待たずにSubscribeを送信しているようです。

スクリーンショット 2025-11-15 21.54.40.jpg

Subscribeのパケットの中身を見てみます。
スクリーンショット 2025-11-15 21.58.46.jpg

UTF-8エンコーディングの通り、Topic Length, Topic
その後に、QoS(それぞれ0x00, 0x01, 0x02)が記載されています。

それに対応するSubackは順番にQoSを含んでいます。
スクリーンショット 2025-11-15 22.07.12.jpg

まとめ

  • Subscribe は複数トピックを一度に購読できる
  • ここで伝達するQoSは「許容する最大値」で、実際の配信は min(PUB QoS, SUB QoS)で決定
  • Subackは1つだけ返るが、その中に複数のReturn Codeを持つ場合もある

著作権情報

Copyright © OASIS Open 2014. All Rights Reserved.
Available at: https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html

Copyright © OASIS Open 2019. All Rights Reserved.
Available at: https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?