CoAP
電力やメモリが限られたIoT機器向けの、軽量なアプリケーション層プロトコル。HTTPに似た要求と応答でデータをやり取りし、基本方式ではUDPを利用する。
イマシルちゃんの解説
電池で長く動かしたい温度センサーでは、通信に使う電力やメモリを抑えることが大切だよ。
そうした小さな機器向けの通信プロトコルがCoAPなんだ。
温度を読み出したり設定を変えたりする要求を送り、機器から結果を返してもらうよ。
通信の制御情報を載せるヘッダーを小さくして、送りたいデータ以外の負担を減らしているんだ。
基本方式では受信確認が必要なメッセージを選べて、確認が返らなければ送り直せるよ。
通信を軽くしながら必要なやり取りを続けられるので、電力やメモリに余裕のない機器でも使いやすいんだ。
この解説はわかりやすかったですか?
より深い解説
定義
CoAP(Constrained Application Protocol)は、IETFがRFC 7252(2014年)で標準化した、制約のある機器(constrained device)と制約のあるネットワーク向けのアプリケーション層プロトコルである。電池で動く小さなセンサーや、パケット損失が多く帯域の狭い無線ネットワーク(6LoWPANなど)での利用を想定している。
HTTPに似た仕組み
CoAPは、HTTPと同じRESTの考え方で設計されている。この考え方に沿う構成をRESTfulと呼ぶ。
サーバ上の資源をURIで指定し、操作の種類をメソッドで表す。例えば coap://sensor.example/temperature は温度という資源を指す。RESTは通信プロトコル名ではなく、資源と統一された操作を中心にシステムを構成する設計の考え方である。
| 基本メソッド | コード | 資源に対する操作 |
|---|---|---|
| GET | 0.01 | 現在の温度などの表現を読み出す |
| POST | 0.02 | 資源にデータを渡して処理させる。子資源の作成にも使う |
| PUT | 0.03 | 指定したURIの資源を作成または更新する |
| DELETE | 0.04 | 指定した資源を削除する |
応答コードは「クラス.詳細」の形で表す。先頭の2は成功を示すが、何が成功したかは後半も見て判断する。
| 応答コード | 意味 |
|---|---|
| 2.01 Created | 資源を作成した |
| 2.02 Deleted | 資源を削除した |
| 2.04 Changed | 資源を変更した |
| 2.05 Content | 資源の表現を応答に載せる |
| 4.04 Not Found | 指定した資源が見つからない |
そのため、CoAPとHTTPを相互に変換するプロキシを置けば、IoT機器のデータを普通のWebの仕組みから扱える。
軽くするための工夫
| 工夫 | 内容 |
|---|---|
| UDPの上で動く | TCPのような接続の確立や管理が不要。標準のポート番号は5683 |
| 小さなバイナリヘッダ | 固定部分はわずか4バイト。HTTPのようなテキストのヘッダではない |
| 必要なときだけ再送 | 下の「メッセージの種類」で、確認が必要なメッセージだけ再送する |
メッセージの種類と信頼性
UDPには再送の仕組みがないため、CoAP自身が簡単な信頼性の仕組みを持つ。
UDPはトランスポート層、CoAPはアプリケーション層のプロトコルである。UDPでは、パケットが順不同で届いたり、重複して届いたり、通知されずに失われたりすることがある。CoAPが必要な確認と再送を追加するが、受信したデータを常に送信順へ並べ直す機能まで提供するわけではない。
| 種類 | 意味 |
|---|---|
| CON(Confirmable) | 確認が必要。相手からACKが返らなければ、間隔を広げながら再送する |
| NON(Non-confirmable) | 確認不要。定期的なセンサー値のように、1回くらい欠けても困らないデータ向け |
| ACK(Acknowledgement) | 確認が必要なメッセージを受け取ったことを知らせる |
| RST(Reset) | 受け取ったが処理に必要な文脈を持たないことなどを知らせる |
この「大事なものだけ確認する」仕組みにより、パケット損失が起きやすいネットワークでも、少ない電力で必要な信頼性を確保できる。
再送では指数バックオフを使う。RFC 7252の既定値では最初の待ち時間を2~3秒の範囲からランダムに選び、再送のたびに待ち時間を2倍にする。最大再送回数は4回であり、無限に再送し続けることはない。時間をずらして再送頻度も下げることで、損失時の通信集中を抑える。
その他の特徴
- Observe:一度登録すると、値が変わるたびにサーバから通知が届く。定期的に問い合わせなくてよいので、電力を節約できる
- マルチキャスト:UDPの上で動くので、複数の機器に一度に問い合わせられる
- ブロック転送:大きなデータを小さなブロックに分けて送れる
- セキュリティ:UDP向けのTLSであるDTLSで暗号化する(ポート番号5684)
MQTTとの違い
IoT向けのプロトコルとして、CoAPとよく比べられるのがMQTTである。
| CoAP | MQTT | |
|---|---|---|
| 通信の形 | 要求と応答(HTTPに似る) | 発行と購読(Publish/Subscribe) |
| 下位のプロトコル | UDP | TCP |
| 仲介役 | なくてよい | ブローカーが必須 |
メッセージと要求を対応付ける識別子
CoAPには、メッセージを対応付けるための値が2つある。
| 値 | 対応付けるもの | 使い道 |
|---|---|---|
| メッセージID | 確認が必要なメッセージと、その受信確認などのメッセージ同士 | 16ビットの値。確認応答の対応付けと重複の検出に使う |
| トークン | 要求と応答 | 0~8バイトの値。後から届く応答も、どの要求に対する結果か対応付ける |
同じ送信元から同じメッセージIDを持つ再送が届いた場合、受信側は通常、資源の変更などを重複して実行しない。ただし受信確認が失われた可能性があるため、必要な確認応答は再び返す。メッセージIDはデータの通し番号ではなく、到着順序を復元するための番号でもない。時系列の測定値を並べたい場合は、測定時刻やアプリケーション独自の連番を持たせる。
応答の返し方
| 方式 | 内容 |
|---|---|
| ピギーバック応答 | 受信確認に結果のデータも載せて返す |
| セパレート応答 | すぐに結果を用意できないときは、まず空の受信確認を返す。後で独立したメッセージとして結果を送る |
セパレート応答を確認付きで返す例では、結果のメッセージに要求とは別のメッセージIDを使い、要求と同じトークンを引き継ぐ。
- 測定結果を準備
要求の受信確認と、処理結果が返る時点は分けられる。このような非同期のやり取りを利用すると、プログラムは結果を待つ間にほかの処理を進められる。ただし同じ相手へ無制限に要求を送り続けてよいという意味ではない。RFC 7252では未完了の相互作用の数を制限するNSTARTの既定値が1であり、輻輳制御の条件に従う。
HTTP/1.1との比較
UDPを使う基本方式にはTCPの接続確立がなく、小さなヘッダーで通信できる。一方、HTTP/1.1も持続的接続を使って同じTCP接続で複数の要求を処理できるため、要求のたびに接続と切断が必須という説明は正しくない。通信量や消費電力は接続の再利用、再送、暗号化、送信頻度にも左右される。
CoAPにもRFC 8323でTCP・TLS・WebSocket上の方式が定義されている。UDP方式の確認メッセージや再送の説明を、そのままTCP方式へ当てはめない。