MQTTバージョン5の概要 第4回 旧バージョンからの主な変更点 4〜

MQTTバージョン5のWD11をもとに、旧バージョン3.1.1からの差分を解説します。長いので３回に分割しています。今回は差分解説の3回目（連載4回目）です。

連載目次

[第1回 標準化の狙い] (http://qiita.com/items/bd21ce2995f313521c56) (2017/2/25)
[第2回 旧バージョンからの主な変更点 1〜3.2] (http://qiita.com/items/71f1e4f4e40d0033822d) (2017/3/9)
[第3回 旧バージョンからの主な変更点 3.3〜3.15]
(http://qiita.com/items/563f2c67639318c5c3d6) (2017/3/12)
[第4回 旧バージョンからの主な変更点 4〜] (http://qiita.com/items/8cf99f01a4dc1530a137) (2017/3/18)
[第5回 考察 MQTTはIoTにおいてHTTP/RESTを完全に駆逐する] (http://qiita.com/items/00cb2050ae68b45bb931) (2017/3/18)

以下では、主要な変更点を、標準書の項番単位で紹介していきます。
<font color="Red">既にこれまでの項番で述べられた変更に再度言及された場合、重要性が少ない記述であれば省略します。</font>

# 4. Operational behavior

## 4.8 Subscriptions

### 4.8.1 Non-Shared Subscriptions
+ 通常の非共有サブスクリプションでは、セッション内で、１つのトピックフィルタに対して1つのサブスクリプションだけが作成可能です。複数のクライアントであれば、1つのトピックフィルタに対してそれぞれのサブスクリプションが作成可能です。

### 4.8.2 Shared Subscriptions
+ 共有サブスクリプションも、非共有サブスクリプションと同様に、複数のセッションと関連づけられます。しかし、共有サブスクリプションでは、ただ1つのセッションにのみメッセージがPUBLISHされます。メッセージコンシューマとなるクライアントが複数並列で存在する場合に便利です。
+ トピックフィルタの形式は、\\$share/{ShareName}/{filter} となります。$shareは共有サブスクリプションのための特別なリテラルです。この形式は、非共有サブスクリプション {filter} とマッチしていることが推奨されます。{ShareName}は共有名であり、これが異なると別の共有サブスクリプションとして扱われます。
+ 共有サブスクリプションのどのセッションにメッセージをPUBLISHするかは、サーバーの実装依存です。
+ 共有サブスクリプションの各セッションのQoSは一致していなくてもかまいません。
+ メッセージをPUBLISHされたクライアントが否定応答した場合には、サーバーはメッセージを削除します。別のセッションを選択しなおすことはしません。

## 4.9 Flow Control
+ Receive Maximumにより、QoS>0について返信を待たずに連続で送信できるメッセージ数が規定されます。最大値に到達したら送信をやめるか、QoS=0で送信する必要があります。
+ Receive Maximumの設定および連続送信クォータは、ネットワークコネクションが切断されるとリセットされます。

## 4.10 Request / Response （要求応答）

### 4.10.1 Basic Request Response (non-normative)

+ 要求応答のやりとりでは、要求側クライアントがPUBLISHしたメッセージを、応答側クライアントがサブスクライブして受信します。応答側はしかるべき処理をした後、Response Topic宛てに応答を返信します。要求側は一般的にResponse Topicをサブスクライブして待ち受けます。
+ 要求メッセージにCorrelation Dataが含まれている場合、応答側クライアントはその内容をコピーして、応答メッセージのCorrelation Dataに書き込むことで、要求と応答の関連付けが可能になります。応答メッセージには、Response Topicは含まれません。
+ サーバーは要求メッセージも応答メッセージも、普通のメッセージと同様に転送します。
+ 通常、要求側は、要求メッセージをPUBLISHする前に、Response Topicをサブスクライブしておきます。Response Topicのサブスクライバーがいない場合、応答メッセージは、どのクライアントにも転送されません。
+ 要求メッセージも応答メッセージも、任意のQoSをとりえます。
+ 応答側は、複数の応答クライアントのプールとして、共有サブスクリプションを利用するこができます。
+ 要求トピックへのPUBLISHと応答トピックへのサブスクライブに対する認可を得ることは要求側の責任です。また、要求トピックへのサブスクライブと応答トピックへのPUBLISHに対する認可を得ることは応答側の責任です。サーバーには、これらの認可機構を実装することを推奨します。

### 4.10.2 Determining a Response Topic Value (Non-Normative)
+ 要求側は任意の方法で応答トピックを決定することができます。多くの場合、応答トピックはクライアントごとに一意なものになります。要求側と応答側が同じトピックの認可を持つ必要がある関係上、ランダムにトピック指定することは困難です。
+ これらの特徴は、要求側が応答トピックを決定する参考になります。CONNECT時にRequest Response Informationプロパティをセットして、サーバからクライアントに対応しトピックフリーなグローバルな応答トピック（クライアント個々のルートトピック）を指定することで、個々のクライアントに応答トピックを定義せずにすみます。

## 4.11 Server redirection
+ サーバーは、クライアントに対して、CONNACKやDISCONNECTのエラーコードとServer Referenceプロパティにより、別のサーバーを指定することが可能です。
+ エラーコード0x9C (Use another server)は一時的なサーバーの移動を、0x9D (Server moved)は恒久的なサーバーの移動を示します。移動先サーバーは予めクライアントに定義してあっても、Server Referenceにより指定しても、どちらでもかまいません。
+ Server Referenceの記述形式は自由ですが、以下の例の形が推奨されます。
  + myserver.xyz.org
  + myserver.xyz.org:8883
  + 10.10.151.22:8883 [fe80::9610:3eff:fe1c]:1883
+ サーバーがServer Referenceを指定するかはオプショナルであり、クライアントが指定されたServer Referenceを守るかどうかもオプショナルです。
+ 本機能は、サーバー負荷分散、サーバー移設、クライアント初期展開<font color="Red">（訳注:工場出荷時はプロビジョニングサーバーにつながるようにして、そこから実サーバのURLを流し込むような用途と思われる）</font>などに利用可能です。

## 4.12 Enhanced authentication
+ MQTT CONNECTパケットは、User NameとPasswordフィールドを持ち、基本的な認証機構を提供します。簡単なパスワード認証だけでなく、Passwordフィールドにトークンを持たせた認証も可能です。
+ 拡張認証は、CONNECTとCONNACKの間でAUTHパケットを交換することにより、チャレンジレスポンスなどが可能になります。
+ 拡張認証はオプショナルです。クライアントがCONNECTでAuth Methodプロパティを使わないなら、サーバーはAUTHパケットや、CONNACKでのAuth Methodを使ってはいけません。サーバーがAUTHパケットやCONNACKでAuth Methodを指定してこない場合、クライアントはAUTHパケットを送ってはいけません。
+ サーバーは、サポートしていないAuth Methodをクラアントが要求した場合、CONNACKでエラーコードを返して、ネットワークコネクションを切断しなければなりません。
+ 認証機構としてSASLをサポートすることを推奨しますが、必須ではありません。
+ 必須ではない例1: SCRAM認証 
  + Client to Server: CONNECT Auth Method="SCRAM-SHA-1" Auth Data=client-first-data 
  + Server to Client: AUTH rc=0x18 Auth Method="SCRAM-SHA-1" Auth Data=server-first-data
  + Client to Server AUTH rc=0x18 Auth Method="SCRAM-SHA-1" Auth Data=client-final-data
  + Server to Client CONNACK rc=0 Auth Method="SCRAM-SHA-1" Auth Data=server-final-data
+ 必須ではない例2: Kerberos認証
  + Client to Server CONNECT Auth Method="GS2-KRB5" 
  + Server to Client AUTH rc=0x18  Auth Method="GS2-KRB5" 
  + Client to Server AUTH rc=0x18 Auth Method="GS2-KRB5" Auth Data=initial context token
  + Server to Client AUTH rc=0x18 Auth Method="GS2-KRB5" Auth Data=reply context token
  + Client to Server AUTH rc=0x18 Auth Method="GS2-KRB5" 
  + Server to Client CONNACK rc=0 Auth Method="GS2-KRB5" Auth Data=outcome of authentication

### 4.12.1 Re-authentication
+ CONNACK完了後に、クライアントはいつでも再認証をすることができる。

## 4.13 Handling errors

### 4.13.1 Malformed Packet and Protocol Errors 
+ クライアントは、不正なパケットやプロトコルエラー、それらのリターンコードを受け取った場合、DISCONNECTパケットを理由付きで送信した後に、ネットワークコネクションを切断しなければなりません。AUTHの場合は、DISCONNECTパケットの送信は任意です。
+ サーバーは、不正なパケットやプロトコルエラー、それらのリターンコードを受け取った場合、DISCONNECTパケットを理由付きで送信した後に、ネットワークコネクションを切断しなければなりません。CONEECTの場合は、DISCONNECTの代わりにCONNACKを使ってもかまいません。

### 4.13.2 Other errors
+ 不正なパケットやプロトコルエラー以外にも、例えば内部的なエラーが発生する可能性があります。その場合は、いろいろなパケットの中でエラーコードを送ることができます。