はじめに
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日目のコードを改造します。サーバ側は変更ありません。
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を送信しているようです。
UTF-8エンコーディングの通り、Topic Length, Topic
その後に、QoS(それぞれ0x00, 0x01, 0x02)が記載されています。
まとめ
- 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


