2. EventReport 报文结构:标准报文头、载荷格式、关键字段
EventReport 报文是嵌入式系统中事件上报与重传机制的核心数据单元。调试丢失与重传问题时,必须首先掌握报文的精确结构。本章从标准报文头、载荷格式、关键字段三个层次展开,并重点解析 EventID、SequenceNumber、Timestamp 三个字段在重传判定中的关键作用。
2.1 标准报文头结构
EventReport 报文头采用固定长度格式,长度为 12 字节。报文头包含协议版本、报文类型、总长度、源地址、目标地址等基础信息。调试时,报文头解析错误是导致重传误判的常见原因之一。
| 偏移 (字节) | 字段名称 | 长度 (字节) | 说明 |
|---|---|---|---|
| 0 | ProtocolVersion | 1 | 协议版本号,当前固定为 0x01 |
| 1 | MessageType | 1 | 报文类型:0x10 表示 EventReport |
| 2-3 | TotalLength | 2 | 整包长度(含报文头),大端序 |
| 4-5 | SourceAddr | 2 | 源设备地址 |
| 6-7 | DestAddr | 2 | 目标设备地址 |
| 8-9 | Reserved | 2 | 保留字段,必须填 0x0000 |
| 10-11 | HeaderChecksum | 2 | 报文头校验和,CRC-16/IBM |
2.2 载荷格式与关键字段
报文头之后是载荷部分。EventReport 的载荷采用 TLV(Type-Length-Value)格式组织,支持灵活扩展。载荷中最重要的三个字段是 EventID、SequenceNumber 和 Timestamp,它们直接参与丢失检测与重传判定。
| 偏移 (相对载荷起始) | 字段名称 | 长度 (字节) | 类型 | 说明 |
|---|---|---|---|---|
| 0-1 | EventID | 2 | uint16 | 事件类型标识,唯一标识一类事件 |
| 2-5 | SequenceNumber | 4 | uint32 | 序列号,单调递增,用于去重和排序 |
| 6-13 | Timestamp | 8 | uint64 | 事件发生时间戳,微秒级精度 |
| 14-15 | PayloadLength | 2 | uint16 | 事件载荷长度(不含本字段) |
| 16+ | PayloadData | 可变 | bytes | 事件具体数据,格式由 EventID 决定 |
- EventID — 区分不同事件类型。接收端根据 EventID 选择对应的处理逻辑和重传策略。
- SequenceNumber — 全局唯一递增序列号。接收端通过检测 SequenceNumber 的连续性判断是否发生丢包。
- Timestamp — 记录事件发生的精确时间。用于计算传输延迟、判断重传超时是否合理。
2.3 关键字段深度解析
2.3.1 EventID — 事件类型标识
EventID 采用 16 位无符号整数,取值范围 0x0001 ~ 0xFFFE。0x0000 保留,0xFFFF 用于测试。调试时,EventID 错误会导致接收端无法正确解析载荷,进而引发重传风暴。
- 标准事件范围: 0x0001 ~ 0x0FFF — 系统预定义事件
- 用户事件范围: 0x1000 ~ 0xEFFF — 应用自定义事件
- 调试事件范围: 0xF000 ~ 0xFFFE — 仅用于调试和测试
2.3.2 SequenceNumber — 序列号与丢包检测
SequenceNumber 是 32 位单调递增计数器,从 0 开始,每发送一个 EventReport 报文自动加 1。接收端维护一个 期望序列号 (ExpectedSeq),通过比较实际接收到的 SequenceNumber 与 ExpectedSeq 来判断是否发生丢包。
2.3.3 Timestamp — 时间戳与超时判定
Timestamp 采用 64 位微秒级时间戳,基于设备本地时钟。在重传机制中,Timestamp 用于计算报文从发送到接收的 往返时间 (RTT),进而动态调整重传超时时间 (RTO)。
2.4 完整报文结构示例
以下是一个完整的 EventReport 报文十六进制示例,包含报文头和载荷。调试时,可以使用此示例验证解析代码的正确性。
// 完整 EventReport 报文 (32 字节)
// 报文头 (12 字节)
01 // ProtocolVersion = 0x01
10 // MessageType = 0x10 (EventReport)
00 20 // TotalLength = 32 字节
00 01 // SourceAddr = 0x0001
00 02 // DestAddr = 0x0002
00 00 // Reserved
A3 B7 // HeaderChecksum (CRC-16/IBM)
// 载荷 (20 字节)
00 0A // EventID = 0x000A (温度告警)
00 00 00 3C // SequenceNumber = 60
00 00 00 00 1A 2B 3C 4D // Timestamp = 439,041,101 μs
00 0A // PayloadLength = 10 字节
01 02 03 04 05 06 07 08 09 0A // PayloadData (10 字节)
2.5 报文结构调试清单
在调试 EventReport 丢失与重传问题时,按以下清单逐项检查报文结构:
- 报文头校验: 验证 HeaderChecksum 是否正确,TotalLength 是否与实际长度一致。
- EventID 合法性: 确认 EventID 在已注册的事件范围内,接收端有对应的解析逻辑。
- SequenceNumber 连续性: 检查接收到的 SequenceNumber 是否严格递增,是否存在跳变或重复。
- Timestamp 合理性: 检查 Timestamp 是否在系统启动时间之后,是否与当前时间偏差过大。
- PayloadLength 一致性: 确认 PayloadLength 与实际载荷数据长度匹配,防止解析越界。