CoAP(Constrained Application Protocol,受限应用协议)是一种计算机协议,专门用于资源受限的物联网设备,具有轻量级、可靠传输和高效数据交换的特点,适用于资源受限的环境。
由于物联网设备的内存和计算能力有限,传统的 HTTP 协议在这些设备上显得过于庞大和复杂。因此,IETF 的 CoRE 工作组提出了基于 REST 架构的 CoAP 协议( RFC 7252)。
CoAP 协议有两个不同的层:消息负载和请求/响应层。消息层处理 UDP 和异步消息,而请求/响应层基于请求/响应消息来管理请求/响应交互。CoAP 消息模型是 CoAP 的最低层,处理端点之间的 UDP 交换消息。每个 CoAP 消息都有一个唯一的 ID,这有助于检测消息重复。CoAP 协议使用两种消息:确认消息和不可确认的消息。确认消息是可靠消息,客户端可以使用这种消息确保消息将到达服务器。而不可确认的消息则不需要服务器确认。
协议特点
- CoAP 协议网络传输层由 TCP 改为 UDP,以适应资源受限设备的需要。
- 它基于 REST 架构,这意味着服务器上的资源地址与互联网中的 URL 格式类似。客户端可以使用类似于 HTTP 的 POST、GET、PUT 和 DELETE 方法来访问服务器,这使得对 HTTP 的请求进行了简化。
- CoAP 采用二进制格式,相比之下,HTTP 是文本格式,因此 CoAP 更加紧凑,可以减少传输的数据量。
- CoAP 协议轻量化,最小长度仅为 4B,相比之下,一个 HTTP 头部可能达到几十个字节。
- CoAP 支持可靠传输、数据重传和块传输,确保数据可靠到达。
- CoAP 还支持 IP 多播,这意味着可以同时向多个设备发送请求。
- CoAP 采用非长连接通信,适用于低功耗物联网场景。这与 TCP 的机制类似,对方必须确认收到消息,以实现可靠的消息传输。
消息类型
CoAP 协议有 4 种消息类型:CON、NON、ACK、RST
CON:需要被确认的请求,如果 CON 请求被发送,那么对方必须做出响应。
NON:不需要被确认的请求,如果 NON 请求被发送,那么对方不必做出回应。这适用于消息会重复频繁的发送,丢包不影响正常操作。
ACK:应答消息,对应的是 CON 消息的应答。
RST:复位消息,可靠传输时候接收的消息不认识或错误时,不能回 ACK 消息,必须回 RST 消息。
消息格式
消息头
必备,固定 4 个 byte。
Ver:2 bit,版本信息,当前为 0x01。
T: 2 bit, 消息类型,包括 CON, NON, ACK, RST 这 4 种。
TKL:4 bit,token 长度, 当前支持 0 ~ 8 B 长度,其他长度保留将来扩展用。
Code:8 bit,分成前 3 bit(0 ~ 7)和后 5 bit(0 ~ 31),前 3 bit 代表类型。
0.00 Indicates an Empty message
0.01-0.31 Indicates a request
1.00-1.31 Reserved
2.00-5.31 Indicates a response.
6.00-7.31 Reserved
Message ID:16 bit, 代表消息 MID,每个消息都有一个 ID ,重发的消息 MID 不变。在一次会话中 ID 总是保持不变。但在这个会话之后该 ID 会被回收利用。
token
可选,用于将响应与请求匹配。 token 值为 0 到 8 字节的序列。每个请求都带有一个客户端生成的 token, 服务器在任何结果响应中都必须对其进行回应。token 类似消息 ID,用以标记消息的唯一性。token 还是消息安全性的一个设置,使用全 8 字节的随机数,使伪造的报文无法获得验证通过。标记是 ID 的另一种表现。
option
可选,0 个或者多个。请求消息与回应消息都可以有零到多个 options。 主要用于描述请求或者响应对应的各个属性,类似参数或者特征描述,比如是否用到代理服务器,目的主机的端口等。CoAP 选项类似于 HTTP 请求头,它包括 CoAP 消息本身,例如 CoAP 端口号,CoAP 主机和 CoAP 查询字符串等。
payload
可选。实际携带数据内容, 若有, 前面加 payload 标识符 “0xFF”,如果没有 payload 标识符,那么就代表这是一个 0 长度的 payload。如果存在 payload 标识符但其后跟随的是 0 长度的 payload,那么必须当作消息格式错误处理。
请求方法(requests)
0.01 GET 方法——用于获得某资源
0.02 POST 方法——用于创建某资源
0.03 PUT 方法——用于更新某资源
0.04 DELETE 方法——用于删除某资源
URI
一个 CoAP 资源可以被一个 URI(Uniform Resource Identifier,统一资源标识符)所描述,例如一个设备可以测量温度,那么这个温度传感器的 URI 被描述为:coap://machine.address/sensors/temperature
CoAP 的 URL 和 HTTP 的有很相似的地方,开头是 “coap” 对应 “http” 或者 “coaps” 对应 “https”。coap 默认端口 UDP 5683,coaps 默认端口是 UDP 5684。默认端口号可以省略。
规则与 http 的 URL 是一样的,比如不区分大小写等。
注:URL(Uniform Resource Locator,统一资源定位器)是一种特定的 URI,这种 URI 还含有如何获取资源的信息(例如 http、coap 等)。
安全性
CoAP 的安全性是用 DTLS 加密实现的。DTLS 的实现需要的资源和带宽较多,如果是资源非常少的终端和极有限的带宽下可能会跑不起来。DTLS 仅仅在单播情况下适用。
通信过程
上面以 GET 流程为例子,有没有发现,其实跟 HTTP 相类似。
-
Client 发起请求,类型是 CON,0.01 代表 GET 请求,MID 是请求消息 ID,URI-Path:temperature 代表请求温度。例如:
coap://example.com:5683/~sensors/temperature
-
Server 收到请求后,就会返回应答 2.05, MID 保持不变,并且返回具体参数 payload 温度 22.3 C
双向收发
基于消息的双向通信(M2M),CoAP Client 与 CoAP Server 双方都可以独立向对方发送请求。双方可当 client 或者 server 角色。传统的 HTTP 协议是主机与 web 服务器之间是单向通信的(用 websocket 除外)。而 CoAP 系统中 CoAP Client 与CoAP Server 是可以双向通信,双方都可以主动向对方发送请求。这也是 CoAP 协议解决物联网场景问题的关键所在。
订阅与发布
MQTT 协议是基于订阅与发布模型的,CoAP 通过扩展协议方式也简单的实现了订阅与发布模型。
当一个客户端需要定期去查询服务器端某个资源的最新状态时,订阅与发布模型就非常有用,不用这个模型,客户端就要周期的不断发送请求到服务器端。
模型框架:
关键概念:
主题 Subject: 代表 CoAP 的某个资源
观察者 Observer:代表对某个 CoAP 资源感兴趣的客户端
登记 Registration: 观察者需要向服务器登记感兴趣的主题
通知 Notification:当观察者感兴趣的主题发生内容变化时,服务器主动通知到观察者
观察协议在 CoAP 基础协议上增加了 1 个 Observe option, 其值为整数,通过该 options 来实现订阅与发布模型管理
在 GET 请求消息里面:
oberser value 为 0: 代表向服务器端订阅一个主题。
oberser value 为 1: 代表向服务器端移除一个已订阅主题。
在 notification 消息里面:
oberser value 代表 主题发生变化时,检测到顺序,以便客户端可以知道状态变化的先后。
客户端向服务器端登记感兴趣的主题 /temperature
当 temperature 发生状态改变时,服务器端主动通知到客户端。
客户端根据 token,就可以与之前订阅主题关联起来,以此确定是哪个主题订阅的。
一个 CoAP Client 可以分次向 CoAP Server 订阅多个资源主题。 一个 CoAP Server 上的主题可以被多个观察者(CoAP Client)订阅。 这样就通过了 CoAP Server 实现了 CoAP Client 之间直接数据转发通信。
可以通过灵活设计服务器上的资源链接,来实现对某个主题的条件订阅(类似触发器或者阀值等)。
比如订阅主题是:
coap://server/temperature/critical?above=42
当温度超过 42,CoAP Server 需要发送通知。