第2章:HSMS 通信基础

各位同学,咱们今天聊聊 HSMS。说实话,HSMS 这个名字听起来挺唬人,什么「高性能半导体消息服务」——但说白了,它就是 SECS-II 消息在 TCP/IP 网络上跑的那条「路」。

我刚开始接触 HSMS 的时候,总觉得它跟普通的 Socket 通信差不多。后来踩了坑才发现,这里面的门道还真不少。今天我就把 HSMS 的协议栈、连接管理、消息格式这些核心内容,掰开了揉碎了讲给你听。

2.1 HSMS 协议栈:三层结构

HSMS 的协议栈分三层,我习惯这么记:

  • 物理层:就是 TCP/IP 网络,说白了就是网线、IP 地址、端口号这些东西
  • 消息层:负责把 SECS-II 消息打包成 HSMS 消息格式,加上消息头
  • 会话层:管理连接的建立、断开、心跳检测

嗯,这里要注意:HSMS 不是从零开始造轮子,它是在 TCP 的基础上加了一层「半导体设备通信的规矩」。你想想看,TCP 只管把数据从 A 传到 B,但传的是什么、怎么解析、连接断了怎么办——这些才是 HSMS 要解决的问题。

核心理解:HSMS = TCP + SECS-II 消息封装 + 连接管理协议

我在项目中遇到过一个问题:设备端和主机端明明 TCP 连接是通的,但就是收不到对方的 SECS-II 消息。查了半天,原来是消息头的 Session ID 没对上。这就是对消息层理解不够深导致的。

2.2 连接建立与断开:三次握手与心跳

HSMS 的连接建立,其实就是在 TCP 连接之上再做一次「应用层握手」。我把它总结成三步:

  1. TCP 连接建立:设备主动连接主机的 5000 端口(默认端口)
  2. 发送 Select.req:设备告诉主机「我要建立 HSMS 会话」
  3. 收到 Select.rsp:主机回复「OK,会话已建立」

为什么会这样设计?因为 TCP 只保证数据能传,但不保证「谁跟谁在通信」。HSMS 的 Select 消息,说白了就是双方互相确认身份。

个人经验:我建议你在实现连接建立时,加一个超时重试机制。曾经有个项目,设备端网络不稳定,Select.req 发出去主机没收到,结果设备一直傻等。加了个 5 秒超时重试,问题就解决了。

断开连接也分两种:

  • 正常断开:发送 Deselect.req / Deselect.rsp,然后关闭 TCP 连接
  • 异常断开:TCP 连接突然中断,或者长时间收不到心跳包

说到心跳,这是 HSMS 里最容易忽略的地方。我曾经遇到过设备运行一整天后突然断连,查日志发现是心跳超时了。心跳包(Linktest.req)默认每 10 秒发一次,如果连续 3 次没收到回复,就认为连接断了。

避坑指南:我曾经把心跳间隔设成了 60 秒,结果主机那边超时设置是 30 秒,导致连接频繁断开。记住:心跳间隔一定要小于对方的超时时间。

2.3 消息格式:Message Header & Data

HSMS 的消息格式,说白了就是「消息头 + 消息体」。消息头固定 10 个字节,消息体就是 SECS-II 的原始数据。

消息头的结构我列个表,你一看就明白:

偏移量 长度(字节) 字段名 说明
0 4 Length 消息体长度(不包括这 4 个字节)
4 2 Session ID 会话标识,设备 ID
6 1 Header Byte 2 消息类型(如 Select.req = 0x01)
7 1 Header Byte 3 保留位或附加信息
8 2 System Bytes 系统字节,用于消息配对

嗯,这里有个关键点:System Bytes。我刚开始做 HSMS 的时候,没太在意这个字段,结果发现回复消息总是对不上请求。后来才明白,每条请求消息的 System Bytes 必须是唯一的,回复消息要原样返回这个值。

举个例子,发送 Select.req 时:

// 消息头示例(十六进制)
00 00 00 00  // Length = 0(Select.req 没有消息体)
00 01        // Session ID = 1
01           // Header Byte 2 = Select.req
00           // Header Byte 3 = 保留
00 0A        // System Bytes = 10

收到 Select.rsp 时,System Bytes 应该是 0x000A,这样你才能知道这是对刚才那条请求的回复。

实战技巧:我习惯用一个递增的计数器来生成 System Bytes,每次发送消息 +1。这样既保证唯一性,排查问题时也能通过 System Bytes 知道消息的发送顺序。

2.4 消息类型一览

HSMS 定义了 7 种消息类型,我按功能分了三类:

  • 连接管理:Select.req/rsp、Deselect.req/rsp、Linktest.req/rsp
  • 数据传输:Data Message(就是普通的 SECS-II 消息)
  • 拒绝消息:Reject.req(对方发来的消息格式不对时回复)

你想想看,这 7 种消息覆盖了 HSMS 通信的所有场景。连接建立用 Select,断开用 Deselect,保活用 Linktest,传数据用 Data Message,出错了用 Reject。

我在项目中见过一个低级错误:有人把 Data Message 的消息头里 Header Byte 2 填成了 0x00,结果主机端解析失败。记住:Data Message 的 Header Byte 2 固定是 0x00。

2.5 知识体系总览

下面这张图是我自己画的 HSMS 通信核心逻辑,你一看就能把今天讲的内容串起来:

HSMS 通信核心逻辑 会话层(连接管理) 消息层(消息格式) 物理层(TCP/IP) TCP 连接建立 Select.req / rsp 数据传输(Data Message) Linktest.req / rsp(心跳) Deselect.req / rsp 消息头(10 字节) 消息体(SECS-II 数据) Length SID B2 B3 SysB 连接状态机 NOT CONNECTED CONNECTING CONNECTED DISCONNECTING TCP 连接 → Select.req → 数据传输/心跳 → Deselect.req → TCP 断开

这张图把今天讲的内容都串起来了。从左到右看:底层是 TCP/IP,上面是消息层和会话层。连接管理走的是「建立→传输→断开」这条线,消息格式就是那 10 个字节的消息头加上 SECS-II 数据。

好了,HSMS 通信基础就讲到这里。记住我说的:System Bytes 要唯一、心跳间隔要匹配、消息头字段别填错。这些坑我都替你踩过了,你照着做就能少走弯路。


专注资料整理