CoAP Option 详解
CoAP(Constrained Application Protocol)是专门为受限环境(如 IoT 设备)设计的应用层协议,它的 Option 机制类似于 HTTP 的头部(Header),但更加轻量和灵活。
Option 的基本结构
格式
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| Option Delta | Option Length | Option Value (变长) ...
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
字段说明:
- Option Delta(4位):当前 Option 与前一个 Option 的编号差值(差分编码,节省空间)
- Option Length(4位):Option Value 的长度(0-12字节直接表示,13-268字节用扩展字节)
- Option Value(变长):Option 的实际数据
差分编码示例
假设要编码 Option 编号:3, 11, 11, 27
实际编码的 Delta 值:3, 8, 0, 16
计算方式:
第1个: 3 - 0 = 3
第2个: 11 - 3 = 8
第3个: 11 - 11 = 0
第4个: 27 - 11 = 16
标准 Option 类型(RFC 7252 + 扩展)
核心 Option(RFC 7252)
| Option编号 | 名称 | 格式 | 说明 | 示例值 |
|---|---|---|---|---|
| 1 | If-Match | opaque | 条件请求,ETag 匹配 | 0x01 0x02 0x03 |
| 3 | Uri-Host | string | 主机名 | “example.com” |
| 4 | ETag | opaque | 实体标签 | 0x8a 0x09 0x3c |
| 5 | If-None-Match | empty | 条件请求(无匹配时处理) | (空) |
| 6 | Uri-Port | uint | 端口号 | 5683 |
| 7 | Location-Path | string | 资源位置路径 | “sensors/temp” |
| 8 | Uri-Path | string | 资源路径 | “temp” |
| 11 | Content-Format | uint | 内容格式(Media Type) | 40 (application/json) |
| 12 | Max-Age | uint | 响应最大有效期(秒) | 60 |
| 14 | Uri-Query | string | 查询参数 | “unit=celsius” |
| 15 | Accept | uint | 客户端接受的格式 | 50 (application/cbor) |
| 17 | Location-Query | string | 位置查询参数 | “id=123” |
| 20 | Proxy-Uri | string | 代理 URI | “coap://proxy/res” |
| 35 | Proxy-Scheme | string | 代理方案 | “coap” |
| 39 | Size1 | uint | 请求体大小估计 | 256 |
常用 Content-Format 值
0 - text/plain
40 - application/json
41 - application/cbor
42 - application/exi
47 - application/link-format
50 - application/octet-stream
60 - application/cose; cose-type="cose-encrypt"
Option 在消息中的组织规则
排序规则 Options 必须按照 Option 编号升序排列:
Uri-Path (8) → Uri-Query (14) → Content-Format (11) ❌ 错误!
Uri-Path (8) → Content-Format (11) → Uri-Query (14) ✅ 正确
重复规则 Option 类型 是否可重复 处理方式 Uri-Path, Uri-Query 是 拼接使用(如: /path1/path2?q1=a&q2=b) ETag, If-Match 是 列表处理 其他大多数 Option 否 最后一个有效 Uri-Path 和 Uri-Query 的特殊处理 text GET coap://server.com/sensors/temp?unit=c&limit=10
实际编码: Uri-Path: “sensors” (Option 8, Delta=8) Uri-Path: “temp” (Option 8, Delta=0) ← 相同编号,Delta=0 Uri-Query: “unit=c” (Option 14, Delta=6) Uri-Query: “limit=10”(Option 14, Delta=0)
实际消息示例
请求消息
CoAP Request: GET /sensors/temperature?unit=celsius
Ver: 1
Type: CON (0)
Code: 0.01 (GET)
MsgID: 0x7d34
Token: 0x31 0x32 0x33 0x34
Options:
Option #3 (Uri-Host): "iot.example.com"
Option #8 (Uri-Path): "sensors"
Option #8 (Uri-Path): "temperature"
Option #14 (Uri-Query): "unit=celsius"
Option #11 (Content-Format): 40 (application/json)
Payload: (空)
字节流表示:
0x44 0x01 0x7d 0x34 0x31 0x32 0x33 0x34
0x33 0x65 0x69 0x6f 0x74 0x2e 0x65 0x78 0x61 0x6d 0x70 0x6c 0x65 0x2e 0x63 0x6f 0x6d
0x88 0x07 0x73 0x65 0x6e 0x73 0x6f 0x72 0x73
0x00 0x0b 0x74 0x65 0x6d 0x70 0x65 0x72 0x61 0x74 0x75 0x72 0x65
0x8d 0x0d 0x75 0x6e 0x69 0x74 0x3d 0x63 0x65 0x6c 0x73 0x69 0x75 0x73
0xb1 0x28
响应消息
CoAP Response: 2.05 Content
Ver: 1
Type: ACK (2)
Code: 2.05 (Content)
MsgID: 0x7d34
Options:
Option #12 (Max-Age): 60
Option #11 (Content-Format): 40 (application/json)
Payload: {"temp": 22.5, "unit": "celsius"}
扩展 Option(常见 RFC)
| RFC | 新增 Option | 说明 |
|---|---|---|
| RFC 7959 | Block1 (27), Block2 (23) | 分块传输,用于大数据 |
| RFC 8323 | TCP_Connection | CoAP over TCP 支持 |
| RFC 8613 | OSCORE (9) | 对象安全(加密/完整性) |
| RFC 8974 | Hop-Limit (16) | 跳数限制(类似 TTL) |
Block2 Option 示例(分块传输)
请求第1块(0-1023字节):
Block2: 0x08 (Size=1024, More=1, Num=0)
→ 0b00001000 = More=1, Num=0, Size=6 (2^(4+6)=1024)
请求第2块(1024-2047字节):
Block2: 0x18 (Size=1024, More=1, Num=1)
→ 0b00011000 = More=1, Num=1, Size=6
最后一块:
Block2: 0x28 (Size=1024, More=0, Num=2)
→ 0b00101000 = More=0, Num=2, Size=6
Option 的设计优势
- 紧凑编码:差分编码 + 长度优化,最小化开销
- 可扩展性:自定义 Option(编号 256+ 为企业私有)
- 顺序处理:简化解析器实现
- 与 HTTP 映射:便于与 Web 系统集成
开发注意事项
解析时:
必须按顺序处理 Option
注意 Delta 的重构:current_number = previous + delta
处理重复 Option 的语义
生成时:
排序 Option 编号
为重复 Option 设置 Delta=0
合理选择 Content-Format
自定义 Option:
// 自定义 Option 编号应 >= 256
#define MY_CUSTOM_OPTION 256
// 注册到 CoAP 库
coap_add_option(response,
COAP_OPTION_NUM(MY_CUSTOM_OPTION),
(uint8_t*)"data", 4);
CoAP Option 的设计体现了物联网协议的核心理念:’在极简的基础上提供足够的灵活性’,是理解 CoAP 协议的关键部分。