3. HSMS 报文结构:消息头(Message Header)解析

HSMS(High-Speed SECS Message Services)是 SECS/GEM 协议在 TCP/IP 网络上的传输层实现。理解 HSMS 报文结构是进行报文捕获与协议解析的基础。每一个 HSMS 报文都由一个固定长度的 消息头(Message Header) 和紧随其后的 数据区(Data Block) 组成。消息头承载了会话控制、消息路由和事务管理的关键信息。

核心要点: HSMS 消息头固定为 14 字节(4 字节长度 + 10 字节头部字段),这是解析任何 HSMS 报文的起点。长度字段决定了整个报文(包括头部本身)的字节数。

3.1 HSMS 报文整体结构

一个完整的 HSMS 报文在 TCP 流中呈现为“长度前缀 + 消息头 + 数据区”的格式。长度前缀是一个 4 字节的无符号整数,用于帧定界。

HSMS 报文整体结构(TCP 载荷) 长度字段 4 字节 消息头(Message Header) 10 字节 数据区(Data Block) N 字节(可选) 总长度 = 4(长度字段)+ 10(消息头)+ N(数据区)

3.2 消息头(Message Header)字段详解

消息头固定为 10 字节,包含 5 个关键字段。下表列出了每个字段的偏移、长度、名称和用途。

偏移(字节) 长度(字节) 字段名称 描述
0 2 Session ID(会话 ID) 标识设备或会话。设备端通常为 0,主机端为 1–32767。
2 1 Header Byte 2(头部字节 2) 包含 RTS(请求/响应)标志位和事务类型。
3 1 Header Byte 3(头部字节 3) 包含消息类型(Message Type)编码。
4 4 System Bytes(系统字节) 用于匹配请求与响应的事务 ID。
8 2 Reserved / Data Length(保留/数据长度) 通常为 0x0000;在部分实现中用于指示数据区长度。
调试技巧: 在 Wireshark 或 SECS 调试工具中,直接查看消息头的 10 个字节即可快速判断会话归属、消息方向和事务类型。System Bytes 是追踪“请求-响应”对的关键。

3.3 长度字段(Length Field)

长度字段位于报文最前端,占用 4 字节(32 位无符号整数,网络字节序)。它表示从消息头开始到报文结束的总字节数,即 10 + N(N 为数据区长度)。

  • 最小值: 10(无数据区,仅消息头)。
  • 最大值: 理论 2³²-1,但实际受 TCP 缓冲区限制。
  • 解析要点: 接收方先读取 4 字节得到长度 L,再读取 L 字节得到完整的消息头+数据区。
// 伪代码:HSMS 报文接收逻辑
uint32_t length = read_uint32_big_endian(socket);  // 读取 4 字节长度
uint8_t* buffer = malloc(length);
read_exactly(socket, buffer, length);              // 读取完整报文
// buffer[0..9] 为消息头,buffer[10..length-1] 为数据区

3.4 会话 ID(Session ID)

Session ID 占用消息头的前 2 字节(偏移 0–1),用于区分不同的通信会话。在单会话模式下,设备端固定为 0,主机端通常为 1。在多会话模式下,该字段用于路由到正确的逻辑设备。

消息头 10 字节布局(Session ID 高亮) Session ID 字节 0-1 HB2 字节 2 HB3 字节 3 System Bytes 字节 4-7 Reserved 字节 8-9 HB2 = Header Byte 2(RTS + 事务类型),HB3 = Header Byte 3(消息类型)

3.5 消息类型(Message Type)

消息类型编码位于消息头的第 4 字节(偏移 3),用于区分 HSMS 控制消息和 SECS 数据消息。下表列出了常见的消息类型值。

消息类型值(十进制) 消息类型名称 方向 说明
0 Data Message 双向 携带 SECS-II 数据(如 S1F1、S6F11 等)
1 Select.req 设备→主机 请求建立会话连接
2 Select.rsp 主机→设备 会话建立响应
3 Deselect.req 双向 请求断开会话
4 Deselect.rsp 双向 断开会话响应
5 Linktest.req 双向 连接测试请求
6 Linktest.rsp 双向 连接测试响应
9 Reject.req 双向 拒绝非法报文
10 Separate.req 双向 分离连接(优雅关闭)
常见误区: 消息类型 0(Data Message)并不等于 SECS-II 消息本身。它仅表示“这是一个数据报文”,具体是 S1F1 还是 S6F11 需要解析数据区中的 SECS-II 流。不要将消息类型与 Stream/Function 混淆。

3.6 系统字节(System Bytes)

系统字节占用消息头的第 5–8 字节(偏移 4–7),共 4 字节。它是一个由发送方生成的唯一事务标识符,用于将响应报文与对应的请求报文匹配。

  • 生成规则: 通常使用递增计数器或时间戳的低 32 位。
  • 匹配机制: 响应报文必须复制请求报文的 System Bytes 值。
  • 调试价值: 在捕获的报文中,通过 System Bytes 可以快速找到“请求-响应”对。
// 示例:System Bytes 匹配逻辑
// 请求报文(设备→主机): System Bytes = 0x00001234
// 响应报文(主机→设备): System Bytes = 0x00001234  ← 必须相同

// 如果 System Bytes 不匹配,说明响应与请求不对应,可能是超时重传或乱序。

3.7 完整报文解析示例

下面是一个实际的 HSMS 报文十六进制转储及其解析过程。

原始字节(十六进制):
00 00 00 0E 00 01 81 00 00 00 00 01 00 00

解析步骤:
1. 长度字段(4 字节): 00 00 00 0E → 14 字节(整个报文长度)
2. 消息头(10 字节):
   - Session ID: 00 01 → 1(主机会话)
   - Header Byte 2: 81 → RTS=1(响应),事务类型=1
   - Header Byte 3: 00 → 消息类型=0(Data Message)
   - System Bytes: 00 00 00 01 → 1
   - Reserved: 00 00
3. 数据区(4 字节): 后续字节为 SECS-II 数据(本例省略)
实战要点: 在 Wireshark 中,HSMS 解析器会自动将长度字段、消息头各字段拆解显示。手动解析时,务必注意网络字节序(Big-Endian)和字段边界对齐。

3.8 消息头字段速查表

下表汇总了消息头各字段的字节偏移、取值范围和常见值,方便现场调试时快速对照。

字段 偏移 长度 取值范围 常见值
Session ID 0 2 0–65535 0(设备),1(主机)
Header Byte 2 2 1 0x00–0xFF 0x81(响应+事务类型1)
Header Byte 3 3 1 0–10 0(Data Message)
System Bytes 4 4 0–2³²-1 递增计数器
Reserved 8 2 通常为 0 0x0000