2. CoAP协议精要
CoAP(Constrained Application Protocol)是 IETF 为受限节点和受限网络设计的 REST 风格应用层协议,运行在 UDP 之上,默认端口 5683,DTLS 加密时使用 5684。它把 HTTP 的“方法 + 资源 + 表示”模型压缩成适合 8 位单片机、NB-IoT、LoRa 等场景的二进制格式。理解 CoAP 的关键,是把它拆成五件事:消息模型、请求/响应方法、选项机制、确认与重传、资源发现与观察模式。
一、消息模型:四类消息与两层结构
CoAP 只有四种消息类型:CON(Confirmable,需确认)、NON(Non-confirmable,不需确认)、ACK(Acknowledgement,确认应答)、RST(Reset,复位)。每个 CoAP 报文由 4 字节固定头、Token、选项和负载组成。固定头中的 Version 固定为 1,Type 占 2 位,TKL 表示 Token 长度(0~8),Code 占 8 位,Message ID 占 16 位。
Code 采用“类.细节”的十进制写法:0.01 表示 GET,0.02 表示 POST,0.03 表示 PUT,0.04 表示 DELETE;2.05 表示 Content,4.04 表示 Not Found,5.03 表示 Service Unavailable。请求与响应可以承载在 CON 或 NON 中,ACK 只用于确认 CON,RST 用于拒绝无法处理的消息。
二、请求/响应方法:GET、POST、PUT、DELETE
CoAP 的方法语义与 HTTP 对齐,但更精简。GET 用于读取资源,应具有幂等性;PUT 用于整体替换资源,也幂等;POST 用于创建或触发处理,不保证幂等;DELETE 用于删除资源,幂等。响应码中,2.01 Created 表示创建成功,2.02 Deleted 表示删除成功,2.04 Changed 表示修改成功,2.05 Content 表示返回内容。
实际工程中,一个温度传感器资源可以设计为 coap://[fd00::1]:5683/sensors/temp。客户端发送 CON GET,服务端返回 2.05 Content,负载为 23.5,Content-Format 选项设为 0(text/plain)。若资源不存在,返回 4.04 Not Found;若服务端过载,返回 5.03 Service Unavailable,并可在响应中携带 Max-Age 提示客户端稍后重试。
三、选项机制:紧凑的 TLV 编码
CoAP 选项采用“增量编码”:每个选项由 Delta、Length、Value 三部分组成。Delta 表示当前选项号与前一个选项号的差值,Length 表示值长度。这种设计让常用选项只占 1 字节,非常适合受限网络。选项号越小越靠前,解析时按号递增。
常用选项包括:Uri-Path(11)用于路径分段,Uri-Query(15)用于查询参数,Content-Format(12)标识负载格式,Accept(17)声明期望的响应格式,Max-Age(14)表示响应可缓存秒数,ETag(4)用于缓存校验,Observe(6)用于观察模式,Block1/Block2(27/23)用于分块传输。以 Uri-Path 为例,路径 /sensors/temp 会被拆成两个 Uri-Path 选项,值分别为 sensors 和 temp。
四、确认与重传:ACK_TIMEOUT 与退避
CON 消息发出后,发送方启动重传定时器。初始超时时间 ACK_TIMEOUT 默认 2 秒,并乘以 1~1.5 之间的随机因子,避免多节点同时重传造成拥塞。若超时未收到 ACK,则重传,重传次数由 MAX_RETRANSMIT 控制,默认 4 次,每次超时时间翻倍。因此最坏情况下总等待时间约为 2+4+8+16+32=62 秒。若仍无 ACK,则判定对端不可达。
接收方收到重复的 CON 时,应重新发送 ACK,而不是重复处理业务。若收到无法识别的消息,可回复 RST。NON 消息不重传,但可携带 Message ID 供接收方去重。工程上,电池供电节点应优先使用 NON 上报周期数据,仅在配置下发、固件升级等关键操作中使用 CON。
五、资源发现与观察模式
资源发现通过 /.well-known/core 实现。客户端发送 GET,服务端返回 CoRE Link Format(Content-Format 40),例如:
</sensors/temp>;rt="temperature";if="sensor",
</sensors/humid>;rt="humidity";if="sensor",
</actuators/led>;rt="light";if="actuator"
客户端据此获知资源路径、资源类型 rt 和接口描述 if,从而动态适配设备能力。观察模式则通过 Observe 选项实现:客户端在 GET 中携带 Observe=0,服务端返回 2.05 并携带 Observe 序号。此后资源变化时,服务端主动推送通知,序号递增。客户端可用 RST 或带 Observe=1 的 GET 取消观察。观察模式让 CoAP 在 UDP 上实现了类似订阅/推送的能力,是传感器数据上云的关键机制。
| 机制 | 关键字段/选项 | 默认值或示例 | 工程作用 |
|---|---|---|---|
| 消息类型 | Type | CON / NON / ACK / RST | 决定可靠性与能耗 |
| 方法 | Code | 0.01 GET、0.03 PUT | 表达资源操作语义 |
| 选项 | Delta + Length + Value | Uri-Path=11、Observe=6 | 紧凑传递元数据 |
| 重传 | ACK_TIMEOUT、MAX_RETRANSMIT | 2 s、4 次 | 保证 CON 可靠到达 |
| 资源发现 | /.well-known/core | Content-Format 40 | 动态发现设备资源 |
| 观察 | Observe 选项 | 0 注册、1 取消 | 实现服务端推送 |
掌握这五个机制后,就能读懂一个 CoAP 报文在受限网络中的完整生命周期:从 CON 发出、选项编码、服务端处理、ACK 确认,到 Observe 持续推送。下一阶段进入 MQTT 协议时,可以逐项对照两者在可靠性、主题模型和推送方式上的差异,为协议转换建立清晰的映射依据。