CoAP 協議設計與實現

1 CoAP 協議

CoAP(Constrained Application Protocol )協議是物聯網中,一種輕量級的 Web 協議,類似於互聯網中的 HTTP 協議。鑑於物聯網設備資源受限,所以使用 CoAP 協議是一種較好的選擇。CoAP 基於 UDP 協議,爲了彌補 UDP 傳輸的不可靠性,CoAP 定義了帶有重傳機制的事務處理機制。

相對於 HTTP,CoAP 有如下特點

  • CoAP 採用二進制報文頭,而非文本
  • CoAP 減少了協議頭的類型
  • CoAP 只支持一些重要的請求方法:POST、GET、PUT、DELETE
  • CoAP 可以支持檢測裝置

CoAP 協議在 TCP/IP 協議棧中的位置

1.1 CoAP 報文格式

CoAP 協議默認端口是 5683,報文格式如下 1

  • Ver【版本version】版本號
  • T【消息類型 Message Type】CON,NON,ACK,RST
  • TKL【Token Length】令牌長度
  • Code【功能碼/響應碼】Code在CoAP請求報文和響應報文中具有不同的表現形式,Code佔一個字節,它被分成了兩部分,前3位一部分,後5位一部分,爲了方便描述它被寫成了c.dd結構。其中0.XX表示CoAP請求的某種方法,而2.XX、4.XX或5.XX則表示CoAP響應的某種具體表現
  • Message ID【消息ID】每個CoAP消息都有一個ID,重發的 MID 不變
  • Token【令牌】將響應與請求匹配
  • Options【選項】CoAP選項類似於HTTP請求頭,它包括CoAP消息本身,例如CoAP端口號,CoAP主機和CoAP查詢字符串等
  • Payload【負載】實際攜帶的數據內容

1.2 Message Type(資源請求/響應模型 )

Coap 協議與 HTTP 一樣,採用請求——響應的工作模式,分爲 CON NON ACK RST 四種:

1 Confirmable Message —— 需要被確認的請求,發送 CON 類型的請求,必須得到響應,類似於 TCP 連接,確保數據的可靠性

                        Client              Server
                           |                  |
                           |   CON [0x7d34]   |
                           +----------------->|
                           |                  |
                           |   ACK [0x7d34]   |
                           |<-----------------+
                           |                  |

2 Non-confirmable Message ——不需要被確認的請求。發送 NON 請求,對方不必迴應,適用於頻繁重複發送的場景,丟包不影響正常工作,類似於 UDP 連接

                        Client              Server
                           |                  |
                           |   NON [0x01a0]   |
                           +----------------->|
                           |                  |

3 Acknowledgement Message —— 應答消息,接受到 CON 消息的響應

4 Reset Message —— 復位消息,當接收者接受到的消息包含一個錯誤,接受者解析消息或者不再關心發送者發送的內容,那麼復位消息將會被髮送

比如某個設備需要從服務器端查詢當前溫度信息

請求消息(CON): GET /temperature , 請求內容會被包在CON消息裏面
響應消息 (ACK): 2.05 Content “22.5 C” ,響應內容會被放在ACK消息裏面

1.3 Code

CoAP 報文中的 Code 字段分爲兩部分:0.00,類似於 HTTP 的狀態碼 2

  • Success 2.xx 代表客戶端請求被成功接收並被成功處理
  • Client Error 4.xx 代表客戶端請求有錯誤,比如參數錯誤等
  • Server Error 5.xx 代表服務器在執行客戶端請求時出錯

CoAP 請求 code 如下

  • 【0.01】GET方法——用於獲得某資源
  • 【0.02】POST方法——用於創建某資源
  • 【0.03】PUT方法——用於更新某資源
  • 【0.04】DELETE方法——用於刪除某資源

CoAP 響應的 code 類型更爲豐富,與 HTTP 響應碼類似

  • 【2.01】Created
  • 【2.02】Deleted
  • 【2.03】Valid
  • 【2.04】Changed
  • 【2.05】Content。類似於HTTP 200 OK
  • 【4.00】Bad Request 請求錯誤,服務器無法處理。類似於HTTP 400
  • 【4.01】Unauthorized 沒有範圍權限。類似於HTTP 401
  • 【4.02】Bad Option 請求中包含錯誤選項
  • 【4.03】Forbidden 服務器拒絕請求。類似於HTTP 403
  • 【4.04】Not Found 服務器找不到資源。類似於HTTP 404
  • 【 4.05】Method Not Allowed 非法請求方法。類似於HTTP 405
  • 【4.06】Not Acceptable 請求選項和服務器生成內容選項不一致。類似於HTTP 406
  • 【4.12】Precondition Failed 請求參數不足。類似於HTTP 412
  • 【4.15】Unsuppor Conten-Type 請求中的媒體類型不被支持。類似於HTTP 415
  • 【5.00】Internal Server Error 服務器內部錯誤。類似於HTTP 500
  • 【5.01】Not Implemented 服務器無法支持請求內容。類似於HTTP 501
  • 【5.02】Bad Gateway 服務器作爲網關時,收到了一個錯誤的響應。類似於HTTP 502
  • 【5.03】Service Unavailable 服務器過載或者維護停機。類似於HTTP 503
  • 【5.04】Gateway Timeout 服務器作爲網關時,執行請求時發生超時錯誤。類似於HTTP 504
  • 【5.05】Proxying Not Supported 服務器不支持代理功能

1.4 Option

CoAP 支持多個 Option,CoAP 的 Option 的表示方法比較特殊,採用增量的方式描述,Option 格式如下

在這裏插入圖片描述
Option 部分包含 Option Delta、Option Length 和 Option Value 三部分,

  • 【Option Delta】表示 Option 的增量,當前的 Option 的具體編號等於之前所有 Option Delta 的總和
  • 【Option Length】表示 Option Value 的具體長度
  • 【Option Value】表示 Option 具體內容

Option 具體內容

   +-----+---+---+---+---+----------------+--------+--------+----------+
   | No. | C | U | N | R | Name           | Format | Length | Default  |
   +-----+---+---+---+---+----------------+--------+--------+----------+
   |   1 | x |   |   | x | If-Match       | opaque | 0-8    | (none)   |
   |   3 | x | x | - |   | Uri-Host       | string | 1-255  | (see     |
   |     |   |   |   |   |                |        |        | below)   |
   |   4 |   |   |   | x | ETag           | opaque | 1-8    | (none)   |
   |   5 | x |   |   |   | If-None-Match  | empty  | 0      | (none)   |
   |   7 | x | x | - |   | Uri-Port       | uint   | 0-2    | (see     |
   |     |   |   |   |   |                |        |        | below)   |
   |   8 |   |   |   | x | Location-Path  | string | 0-255  | (none)   |
   |  11 | x | x | - | x | Uri-Path       | string | 0-255  | (none)   |
   |  12 |   |   |   |   | Content-Format | uint   | 0-2    | (none)   |
   |  14 |   | x | - |   | Max-Age        | uint   | 0-4    | 60       |
   |  15 | x | x | - | x | Uri-Query      | string | 0-255  | (none)   |
   |  17 | x |   |   |   | Accept         | uint   | 0-2    | (none)   |
   |  20 |   |   |   | x | Location-Query | string | 0-255  | (none)   |
   |  35 | x | x | - |   | Proxy-Uri      | string | 1-1034 | (none)   |
   |  39 | x | x | - |   | Proxy-Scheme   | string | 1-255  | (none)   |
   |  60 |   |   | x |   | Size1          | uint   | 0-4    | (none)   |
   +-----+---+---+---+---+----------------+--------+--------+----------+

1.5 Content-Format

和 HTTP 協議一樣,CoAP 支持多種媒體類型,CoAP 協議中關於媒體類型的定義比較簡單,未來可能會擴展

   +--------------------------+----------+----+------------------------+
   | Media type               | Encoding | ID | Reference              |
   +--------------------------+----------+----+------------------------+
   | text/plain;              | -        |  0 | [RFC2046] [RFC3676]    |
   | charset=utf-8            |          |    | [RFC5147]              |
   | application/link-format  | -        | 40 | [RFC6690]              |
   | application/xml          | -        | 41 | [RFC3023]              |
   | application/octet-stream | -        | 42 | [RFC2045] [RFC2046]    |
   | application/exi          | -        | 47 | [REC-exi-20140211]     |
   | application/json         | -        | 50 | [RFC7159]              |
   +--------------------------+----------+----+------------------------+
  • 【text/plain】 編號爲 0,表示負載爲字符串形式,默認爲 UTF8 編碼
  • 【application/link-format】編號爲 40,CoAP 資源發現協議中追加定義,該媒體類型爲CoAP 協議特有
  • 【application/xml】編號爲 41,表示載荷類型爲 XML 格式
  • 【application/octet-stream】編號爲 42,表示負載類型爲二進制格式
  • 【application/exi】編號爲 47,表示負載類型爲簡單的 XML

2 CoAP 案例

下圖顯示了一個簡單的 CoAP 請求與響應,CoAP 請求採用 CON 報文,因此 Server 接收到CON 報文必須返回一個 ACK 報文,ACK 報文的負載含有客戶端想獲取的信息。

在這裏插入圖片描述

CoAP 請求採用 0.01 GET 方法。如果服務端收到消息並正確處理,會返回 2.05 狀態碼(類似於 HTTP 200),請求和響應的 MID 必須完全相同,此處爲 0x7d34。請求響應中的 Token 域爲空。CoAP 請求中包含 Option,該 Option 的類型爲 Uri-Path,那麼 Option Delta 的值爲0+11=11。下圖是具體的報文內容

在這裏插入圖片描述

3 CoAP 協議測試

CoAP 常用的輔助測試工具如下

  • Chrome/Firefox 插件 Copper
  • Coap-cli
  • libcoap

3.1 CoAP-cli

是基於 NodeJS 的命令行工具,使用 npm(NodeJS 包管理器)即可安裝,當然你首先得安裝 npm(NodeJS 自帶,安裝 NodeJS 即可)

npm install coap-cli -g

-g 命令,添加全局變量,讓我們能夠在命令行中直接使用 coap 命令,接下來就可以直接使用 coap 命令進行相關操作,例如使用 coap get 訪問 coap 服務器的資源

在這裏插入圖片描述
測試服務器地址

coap://vs0.inf.ethz.ch/
coap://iot-coap.phodal.com/id/1

3.2 libcoap

3.2.1 安裝

libcoap 是一個開源的 coap 協議實現

git clone https://github.com/obgm/libcoap.git
cd libcoap
./autogen.sh
./configure --disable-doxygen --disable-manpages --disable-dtls
make
make install

configure 依據 Makefile.in 來生成一個符合慣例的 Makefile,configure 可以添加選項,防止因爲系統缺少依賴而無法生成相關 Makefile 文件,比如出現以下 configure error,按照提示即可解決問題

configure: error: ==> Option '--enable-dtls' is set but none of the needed cryptography libraries GnuTLS, OpenSSL or mbed TLS could be found!
                        Install at least one of the package(s) that contains the development files for GnuTLS (>= 3.3.0), OpenSSL(>= 1.1.0), or mbed TLS(>= 2.7.10)
                        or disable the DTLS support using '--disable-dtls'.

如果想移植 libcoap,可以在配置時,添加交叉編譯器的選項

./configure --host=gcc-aarch64-linux-gnu

注意:libcoap 默認會把動態鏈接庫安裝在 /usr/local/lib 目錄中,系統默認加載庫的路徑是 /usr/lib/lib,不包含此目錄,所以直接運行 coap 命令,會出現以下錯誤

在這裏插入圖片描述
將 /usr/local/lib 添加到環境變量中即可

export LD_LIBRARY_PATH=/usr/local/lib

3.2.2 使用

coap-server 創建 coap 服務端

coap-server

客戶端獲取數據

root@kali:~# coap-client -m get coap://localhost
This is a test server made with libcoap (see https://libcoap.net)
Copyright (C) 2010--2020 Olaf Bergmann <[email protected]> and others

如果提示 Address already in use 如下所示

在這裏插入圖片描述
直接關閉佔用端口的相應進程即可

在這裏插入圖片描述

3.3 coapper

coapper 是一個 chrome 瀏覽器插件 3,用於訪問 coap 協議的資源。首先將 github 上的源碼下載下來,解壓後運行

# Windows
install.bat
# Linux
install.sh

打開 chrome 瀏覽器,找到擴展程序(chrome://extensions),開啓 開發者模式 選項,選擇 加載已解壓的擴展程序,添加 coapper 源碼目錄中的 app 以及 extension

在這裏插入圖片描述
此時,在 chrome 瀏覽器的擴展程序界面,應該能夠看到如下界面

修改 coapper 源碼中的 appid,將 Copper4Cr\extension\endpoint\ClientPortChrome.js 文件中的 appid 改爲上述 ID,完成安裝。
在這裏插入圖片描述

4 附錄

CoAP 協議的常用開源代碼實現 4

名稱 開發語言 CoAP版本 客戶端/服務端 實現的CoAP特徵 開源協議 項目鏈接地址
Californium Java RFC 7252 Client + Server Observe, Blockwise Transfers, DTLS EPL+EDL https://www.eclipse.org/californium
cantcoap C++/C RFC 7252 Client + Server   BSD https://github.com/staropram/cantcoap
CoAP implementation for Go Go RFC 7252 Client + Server Core + Draft Subscribe MIT https://github.com/dustin/go-coap
CoAP.NET C# RFC 7252, coap-13, coap-08, coap-03 Client + Server Core, Observe, Blockwise Transfers 3-clause BSD https://github.com/smeshlink/CoAP.NET
CoAPSharp C#, .NET RFC 7252 Client + Server Core, Observe, Block, RD LGPL http://www.coapsharp.com
CoAPthon Python RFC 7252 Client + Server + Forward Proxy + Reverse Proxy Observe, Multicast server discovery, CoRE Link Format parsing, Block-wise MIT https://github.com/Tanganelli/CoAPthon
Copper JavaScript (Browser Plugin) RFC 7252 Client Observe, Blockwise Transfers 3-clause BSD https://github.com/mkovatsc/Copper
https://addons.mozilla.org/de/firefox/addon/copper-270430/
eCoAP C RFC 7252 Client + Server Core MIT https://gitlab.com/jobol/ecoap
Erbium for Contiki C RFC 7252 Client + Server Observe, Blockwise Transfers 3-clause BSD http://www.contiki-os.org/ (er-rest-example)
ETRI CoAP C RFC 7252 Client + Server Core, Observe, Block Commercial http://coap.or.kr/index_en.html
iCoAP Objective-C RFC 7252 Client Core, Observe, Blockwise Transfers MIT https://github.com/stuffrabbit/iCoAP
jCoAP Java RFC 7252 Client + Server Observe, Blockwise Transfers Apache License 2.0 https://code.google.com/p/jcoap/
libcoap C RFC 7252 Client + Server Observe, Blockwise Transfers BSD/GPL http://sourceforge.net/projects/libcoap/develop
microcoap C RFC 7252 Client + Server   MIT https://github.com/1248/microcoap
nCoap Java RFC 7252 Client + Server Observe BSD https://github.com/okleine/nCoAP
node-coap Javascript RFC 7252 Client + Server Core, Observe, Block MIT https://github.com/mcollina/node-coap
Ruby coap Ruby RFC 7252 Client + Server (david) Core, Observe, Block, RD MIT, GPL https://github.com/nning/coap
https://github.com/nning/david
Sensinode C Device Library C RFC 7252 Client + Server Core, Observe, Block, RD Commercial https://silver.arm.com/browse/SEN00
Sensinode Java Device Library Java SE RFC 7252 Client + Server Core, Observe, Block, RD Commercial https://silver.arm.com/browse/SEN00
Sensinode NanoService Platform Java SE RFC 7252 Cloud Server Core, Observe, Block, RD Commercial https://silver.arm.com/browse/SEN00
SMCP C RFC 7252 Client + Server Core, Observe, Block MIT https://github.com/darconeous/smcp
SwiftCoAP Swift RFC 7252 Client + Server Core, Observe, Blockwise Transfers MIT https://github.com/stuffrabbit/SwiftCoAP
TinyOS CoapBlip nesC/C coap-13 Client + Server Observe, Blockwise Transfers BSD http://docs.tinyos.net/tinywiki/index.php/CoAP
txThings Python (Twisted) RFC 7252 Client + Server Blockwise Transfers, Observe (partial) MIT https://github.com/siskin/txThings/

  1. https://tools.ietf.org/html/rfc7252 ↩︎

  2. https://blog.csdn.net/xukai871105/article/details/45167069 ↩︎

  3. https://github.com/mkovatsc/Copper4Cr ↩︎

  4. https://my.oschina.net/RainyZou/blog/1605334 ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章