MQTTのv3.1.1とv5.0のPUBLISH再送信は再接続時が基本

MQTTのv3.1.1とv5.0において、PUBLISH (PUBREC, PUBREL) の再送は、再接続に実施されることが基本となっている。特にv5.0では、v3.1.1と異なり、再接続時以外での再送を明示的に禁止している。

まずv3.1.1から引用する
https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718103

4.4 Message delivery retry
When a Client reconnects with CleanSession set to 0, both the Client and Server MUST re-send any unacknowledged PUBLISH Packets (where QoS > 0) and PUBREL Packets using their original Packet Identifiers [MQTT-4.4.0-1]. This is the only circumstance where a Client or Server is REQUIRED to redeliver messages.

Non normative comment
Historically retransmission of Control Packets was required to overcome data loss on some older TCP networks. This might remain a concern where MQTT 3.1.1 implementations are to be deployed in such environments.

つぎにv5から引用する
https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901238

4.4 Message delivery retry
When a Client reconnects with Clean Start set to 0 and a session is present, both the Client and Server MUST resend any unacknowledged PUBLISH packets (where QoS > 0) and PUBREL packets using their original Packet Identifiers. This is the only circumstance where a Client or Server is REQUIRED to resend messages. Clients and Servers MUST NOT resend messages at any other time [MQTT-4.4.0-1].

If PUBACK or PUBREC is received containing a Reason Code of 0x80 or greater the corresponding PUBLISH packet is treated as acknowledged, and MUST NOT be retransmitted [MQTT-4.4.0-2].

いずれも "When a Client reconnects with ... , both the Client and Server MUST re-send any unacknowledged PUBLISH Packets (where QoS > 0) and PUBREL Packets using their original Packet Identifiers" とある。つまり、再接続時にはACKを受け取っていないPUBLISHやPUBRELを再送しなくてはならない。

次にv3.1.1の引用にある "Non normative comment" に着目すると、古いTCP/IP実装ではControl Packetの再送が必要かもしれないと言っている。つまり、v3.1.1では、「再送信は再接続時に必須」という基本はありつつ、再接続を待たずにControl Packetを再送してもよい、と読める。

次にv5の引用を見ると "This is the only circumstance where a Client or Server is REQUIRED to resend messages. Clients and Servers MUST NOT resend messages at any other time" とある。つまり、「再送信は再接続時に必須」かつ「再接続時以外には再送禁止」と言っている。

実際のところ、v3.1.1実装の機器を使っていると、再接続を待たずに再送している場合があるように思う。