#このページで確認できること
- CONNECT → SUBSCRIBE → PUBLISH の基本フローをシーケンスで確認する
- QoS 0 / 1 / 2 の配送保証の違いをパケットの往復で確認する
- retained message と Last Will (LWT) の動きを mosquitto CLI で試す
- Wireshark の
mqttフィルタで CONNECT / PUBLISH の中身を確認する - 観察する項目: トピック名、QoS フラグ、keep alive と PINGREQ / PINGRESP
実装上の制約: 公開ブローカーは本サイトでは提供していません。以下のコマンド例は Docker でローカルに mosquitto を立てる前提です。
#基本フロー
MQTTのpublish / subscribeモデルでは、クライアント間のメッセージ配送はブローカーを経由します。送信側はトピック(例: lab/sensor/temp)へ publish し、受信側はトピックフィルタを subscribe します。フィルタでは + が1階層に一致し、# が0階層以上に一致する複数階層ワイルドカードです。# はフィルタの最後に置く必要があります。
participants: Publisher, Broker, Subscriber Subscriber -> Broker: CONNECT (client id, keep alive) Broker --> Subscriber: CONNACK Subscriber -> Broker: SUBSCRIBE (lab/#, QoS 1) Broker --> Subscriber: SUBACK Publisher -> Broker: CONNECT Broker --> Publisher: CONNACK Publisher -> Broker: PUBLISH (lab/sensor/temp, QoS 1) Broker --> Publisher: PUBACK Broker -> Subscriber: PUBLISH (lab/sensor/temp) Subscriber --> Broker: PUBACK
QoS — 配送保証の3段階
| QoS | 送信者・受信者間の配送保証 | パケットの往復 | 用途例 |
|---|---|---|---|
| 0 | 最大1回 (fire and forget) | PUBLISH のみ | 欠けてもよい定期計測値 |
| 1 | 少なくとも1回 (重複あり得る) | PUBLISH → PUBACK | 損失を避けたい通知 |
| 2 | ちょうど1回 | PUBLISH → PUBREC → PUBREL → PUBCOMP | MQTTホップで重複配送を避けたいメッセージ |
MQTT仕様にプロトコル全体の「既定QoS」はなく、送信時や購読時に選択します。例で使うmosquitto CLIは -q を省略するとQoS 0です。またQoS 2の「ちょうど1回」はMQTTの送信者・受信者間でのメッセージ配送を指し、アプリケーションの副作用や複数ホップを含むエンドツーエンド処理が必ず1回になることまでは保証しません。
- retained message: トピックの最新値をブローカーが保持し、新規購読者へ即座に配る。「最後の計測値」の表現に使う。
- Last Will (LWT): クライアントのネットワーク接続が通常終了以外の条件で閉じたときなどに、ブローカーが代わりに publish するメッセージ。MQTT 5.0でWill Delayを指定した場合は即時とは限らない。
- keep alive: CONNECT で申告した間隔内に通信がないと、クライアントは PINGREQ を送る。NAT / ファイアウォールのセッションタイムアウトより短く設定するのが実務上の要点。
#検証コマンド
mosquitto — ローカルブローカーと CLI# ブローカーを起動 (匿名接続を許可する検証用設定) $ docker run --rm -p 127.0.0.1:1883:1883 eclipse-mosquitto sh -c \ "echo -e 'listener 1883\nallow_anonymous true' > /tmp/m.conf && mosquitto -c /tmp/m.conf" # 購読 (別ターミナル。-v でトピック名も表示) $ mosquitto_sub -h localhost -t 'lab/#' -v # QoS 1 で publish $ mosquitto_pub -h localhost -t 'lab/sensor/temp' -m '23.5' -q 1 # retained message を置いてから購読してみる $ mosquitto_pub -h localhost -t 'lab/status' -m 'online' -r $ mosquitto_sub -h localhost -t 'lab/status' -v # 接続直後に届くexpected (mosquitto_sub の出力)
lab/sensor/temp 23.5
lab/status online ← retained: 購読した瞬間に配られる
tcpdump / Wireshark
$ sudo tcpdump -i lo0 -n 'tcp port 1883' # Wireshark filter: mqtt — CONNECT / SUBSCRIBE / PUBLISH がデコードされ、 # トピック名とペイロードが平文で読める (1883 の場合)
#観測ポイント
| CLI | mosquitto_sub -d / mosquitto_pub -d のデバッグ出力で CONNECT / CONNACK / PUBACK の往復を確認。QoS を 0/1/2 で変えてパケット数の違いを見る。 |
|---|---|
| Proxy | ネイティブMQTTを通常のHTTPリクエストとして転送することはできない。プロキシのポートポリシーが許せばCONNECTで8883をTCPトンネルする方法があり、別案としてMQTT over WebSocketを443で利用できる。実際の経路とプロキシ対応を確認する。 |
| tcpdump / Wireshark | フィルタ: mqtt。1883 ならトピック・ペイロードが平文で見える。8883 は TLS のため TLS の観測手順(SNI、証明書)が先に必要。 |
| TLS inspection | 8883 の MQTT over TLS は装置によって「復号対象外ポート」の場合がある。クライアント証明書認証(相互TLS)を使うIoTデバイスは、デバイスと装置の信頼設定や実装によっては復号経路で接続に失敗する。対応可否と復号除外の要否を確認する。 |
| NAT / FW | keep alive がセッションタイムアウトより長いと、静かな接続が NAT テーブルから消えて silent drop になる。LWT が発火するまでの時間と keep alive の関係を観測する。 |
#関連
ブラウザから MQTT を使う場合は WebSocket 上で動かします(ws://host/mqtt)。8883 の暗号化は TLS を参照。仕様は OASIS の MQTT 5.0 / 3.1.1 が一次情報です。