本节摘要:把 CoAP 的四个方法 GET/POST/PUT/DELETE 的语义讲清,再拆重传机制(CON 超时退避)与 Block-wise 大载荷传输,最后深入观察者 Observe——设备如何以"订阅式"方式被持续告知资源变化。承接 4.2 报文,通往 4.4 安全与落地。
CoAP 的价值不止"能读一个资源",更在于"想办法让受限设备省电地把变化告诉关心者"。本节先把四个方法定调,再讲重传、分块与观察这套撑起实用性的机制。
# 方法语义速记 GET 读当前表示 # 温度 状态 只读 POST 触发动作/建子资源 # 上报/重配 非幂等 PUT 整体更新 幂等 # 写值 设定 多次等价 DELETE 移除资源 # 删除目标
CoAP 的可靠来自对 CON 消息的应答与重试。默认参数是:ACK 超时约 2 秒,指数退避,最多重传 4 次。退避让重发不至于在弱网下轰垮链路:
重传间隔按指数翻倍(约 2s→4s→8s),既保证最终送达,又避免重发风暴。这正是"把可靠性搬进应用层"的具体体现。
受限节点内存小,一次装不下大响应很正常。CoAP 用 Block-wise 传输把大载荷切成若干块,每块都带偏移号,客户端像翻页一样逐块请求,最后拼回。典型场景是固件更新、大配置下发。对抄表这类小消息并不需要,这里只为完整起见提一句:当你遇到"响应太大装不下"时,就轮到分块登场。
受限节点最怕高频轮询——每问一次都耗电。CoAP 的观察者(Observe)机制扭转了模型:客户端对某个资源发一个带 Observe 选项的 GET,服务器随后在该资源变化时主动推送通知,而非等客户端来问。
Observe 利在省电:客户端一次订阅,长期被动收更新,代价是服务器要维护一份观察者名单。它和 MQTT 的"订阅主题"殊途同归,但定位更细——是理解 CoAP 与 MQTT 的分水岭概念之一。
方法易记,但"哪个幂等、能不能缓存、适合读还是写"常年分不清。用一张表一次钉死(REST 语义,与 HTTP 同构):
| 方法 | 语义 | 幂等 | 可缓存 | 典型用途 |
|---|---|---|---|---|
| GET | 读资源表示 | 是 | 是 | 采温度、查状态 |
| POST | 触发动作/建子资源 | 否 | 视实现 | 触发上报、重配参数 |
| PUT | 整体替换资源 | 是 | 否 | 设定目标值多次等价 |
| DELETE | 删除资源 | 是 | 否 | 移除用例 |
为什么"幂等"这么要紧?在 UDP 上方法可能被重发(CON 重传/去重),若用 POST 做了"累加计数"这类非幂等操作,重发就会多计;而 PUT("设成 25")重发多少次结果都一样。所以对可能重发的控制操作,优先用幂等的 PUT 而非 POST——这一条在弱网设备上尤其能救命。
CoAP 的 Observe 常被拿来与 MQTT 订阅相提并论,但两者有微妙差别:MQTT 订阅的是"主题、全局的、广播式",服务器把匹配消息推给所有订阅者;CoAP 的 Observe 观察的是"某一个资源、点对点的、单客户单资源",且由服务器主动推送该资源自身的变化。换句话说,Observe 更像"对单个状态的持续关注",不承担主题路由那套体系。理解这个粒度之差,才不会在换到第 6 章做协议对比时把两者误当成同一种机制。
纸上讲完机制,值得用思路上最简的方式理一遍"观察"的收发语义(示意为主,聚焦 Token 与回调):
# 观察者侧伪流程 1 发起 Observe GET /temperature Token=T5 2 收到首个 2.05 即当前值 3 此后每当资源变更, 服务器带上同一 Token=T5 再推 2.05 4 想结束观察: 回 RST 或重新 GET 不带 Observe 选项
这段伪流程把"一次订阅、长期被动收更新"的三句收束了。实际编码时,多数 CoAP 库已封装 observe 回调,你只需关心资源 URI 与回调处理,协议层的 Token 对齐由库代劳。
CoAP 的 Observe 通知默认可能走 CON 也可能走 NON。轮询型数据(如每秒温度)用 NON 增补、丢了拉倒;关键状态(如开关是否烧了)用 CON 保证收到。把"可丢"与"不可丢"用消息类型显式分开,是省电又不掉链子的关键操作。
💡 关键直觉:Observe 本质是"把推 vs 拉"的定价权交给协议——服务器推一次,比客户端问十次省十倍电能,这正是受限节点的命门。
4.4 把这套 REST 世界搬上安全底座——DTLS 加密与受限节点的落地取舍。