第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 连接之上再做一次「应用层握手」。我把它总结成三步:
- TCP 连接建立:设备主动连接主机的 5000 端口(默认端口)
- 发送 Select.req:设备告诉主机「我要建立 HSMS 会话」
- 收到 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 通信核心逻辑,你一看就能把今天讲的内容串起来:
这张图把今天讲的内容都串起来了。从左到右看:底层是 TCP/IP,上面是消息层和会话层。连接管理走的是「建立→传输→断开」这条线,消息格式就是那 10 个字节的消息头加上 SECS-II 数据。
好了,HSMS 通信基础就讲到这里。记住我说的:System Bytes 要唯一、心跳间隔要匹配、消息头字段别填错。这些坑我都替你踩过了,你照着做就能少走弯路。