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 URL

在 HTTP 的世界中,RESTFul 协议由于其简单性和适用性,在 WEB 应用中越来越受欢迎,这样的道理同样适用于 CoAP。一个 CoAP 资源可以被一 个URI 所描述,例如一个设备可以测量温度,那么这个温度传感器的URI被描述为:CoAP://machine.address:5683/sensors/temperature。CoAP的默认 UDP 端口号为5683。

1.2 CoAP 订阅/观察模式

当我们需要去监控某个传感器例如温度或湿度等,CoAP客户端并不需要不停的查询 CoAP服务器端的数据变化情况。CoAP 提供了一种观察模式,可以理解为订阅模式,CoAP客户端可以发送一个观察请求到服务器端。从该时间点开始计算,服务器便会记住客户端的连接信息,一旦温度发生变化,服务器将会把新结果发送给客户端。如果客户端不在希望获得温度检测结果,那么客户端将会发送一个 RST 复位请求,此时服务器便会清除与客户端的连接信息。

1.3 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.4 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.5 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.6 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)   |
   +-----+---+---+---+---+----------------+--------+--------+----------+

CoAP协议中支持多个Option,例如

  • 第一个Option Delta=11,表示该Option表示Uri-Path(11)
  • 第二个Option Delta=1,表示该Option=1+11,表示Content-Format(12)
  • 第三个Option Delta=3,表示该Option=3+1+11,表示Uri-Query(15)

1.7 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 ↩︎

猜你喜欢

转载自blog.csdn.net/song_lee/article/details/105599391