3、HSMS通信协议:连接建立与断开、消息格式、会话管理、超时与重传机制
HSMS,全称是High-Speed SECS Message Services。说白了,它就是SECS/GEM协议在TCP/IP网络上的“运输工具”。
我刚开始接触半导体设备通信时,总觉得HSMS很神秘。后来做项目多了才发现,它本质上就是一个可靠的消息传输层。你想想看,设备端和主机端要交换数据,总得有个规矩——怎么连、怎么发、怎么断、出错了怎么办。HSMS就是干这个的。
3.1 HSMS连接建立与断开
HSMS的连接管理,其实就两个动作:建立连接和断开连接。但这里面有不少细节,我踩过坑,所以重点说说。
3.1.1 连接建立流程
HSMS的连接建立,用的是“主动方-被动方”模式。通常设备端是被动方,主机端是主动方。但这不是绝对的,我在项目中就遇到过设备端主动发起连接的情况。
标准的建立流程是这样的:
- TCP连接建立:主动方发起TCP三次握手,建立底层连接。
- HSMS Select过程:主动方发送Select.req消息,被动方回复Select.rsp。
- 连接就绪:双方进入通信状态,可以收发数据了。
这里有个关键点——Select过程必须在TCP连接建立之后立即进行。我曾经见过一个案例,工程师在TCP连接建立后等了5秒才发Select.req,结果对方直接断开了连接。为什么?因为HSMS协议规定了一个超时时间T5,默认10秒内必须完成Select过程。
核心要点:HSMS连接 = TCP连接 + Select过程。缺一不可。
3.1.2 连接断开流程
断开连接有两种方式:正常断开和异常断开。
正常断开:
- 发送Deselect.req消息,等待Deselect.rsp回复。
- 然后关闭TCP连接。
异常断开:
- 直接关闭TCP连接,不发送任何HSMS消息。
- 对方通过超时机制检测到连接断开。
我个人习惯,在正常关机或维护时一定要走正常断开流程。为什么?因为对方需要知道你是“主动下线”还是“意外掉线”。这在生产环境中很重要,主机端会根据断开类型决定是否报警。
注意:不要直接kill TCP连接!除非是紧急情况。否则对方会认为发生了网络故障,可能触发不必要的报警。
3.2 HSMS消息格式
HSMS的消息格式其实很简单,就一个头部加一个数据体。但简单归简单,里面的字段一个都不能错。
3.2.1 消息头部结构
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| Length | 4 | 消息总长度(不包括这4个字节) |
| Device ID | 2 | 设备ID,通常为0 |
| Message ID | 2 | 消息ID,用于匹配请求和响应 |
| Message Type | 1 | 消息类型,如Select.req、Data等 |
| Session ID | 1 | 会话ID,通常为0 |
| Header Byte 2 | 1 | 保留位或扩展位 |
| Header Byte 3 | 1 | 保留位或扩展位 |
嗯,这里要注意一个细节——Length字段。它表示的是“后面所有数据的总长度”,不包括它自己。我刚开始写代码时,经常把这个算错,导致对方解析失败。后来我养成了一个习惯:先算好总长度,再填充头部。
3.2.2 消息类型定义
HSMS定义了多种消息类型,常用的就这几个:
- Select.req (0x01):连接建立请求
- Select.rsp (0x02):连接建立响应
- Deselect.req (0x03):连接断开请求
- Deselect.rsp (0x04):连接断开响应
- Linktest.req (0x05):链路测试请求
- Linktest.rsp (0x06):链路测试响应
- Data (0x07):数据消息,承载SECS-II内容
- Reject.req (0x09):拒绝请求
你可能会问,为什么要有Linktest?说白了就是心跳包。TCP本身有保活机制,但HSMS定义了自己的心跳,更可控。我在项目中一般设置Linktest间隔为30秒,这样既能及时发现网络问题,又不会太频繁占用带宽。
3.3 会话管理
HSMS的会话管理,核心就是“一个TCP连接对应一个会话”。但实际项目中,一个设备可能和多个主机通信,这就涉及到多会话的问题。
我记得有个项目,设备需要同时和MES系统、EAP系统通信。一开始我图省事,只建了一个TCP连接。结果两个系统同时发请求时,消息ID冲突了,数据全乱了。后来我改成每个系统一个独立的TCP连接,每个连接一个独立的会话,问题就解决了。
会话管理的几个关键点:
- 会话ID:每个会话有唯一的ID,用于区分不同的连接。
- 会话状态:包括未连接、已连接、通信中、断开中等。
- 会话超时:长时间无数据交换时,自动断开会话。
经验之谈:多会话场景下,一定要做好会话ID的分配和回收。我习惯用一个全局的ID生成器,每次新建会话时分配一个递增的ID,会话关闭时回收。
3.4 超时与重传机制
这部分是HSMS协议的精髓,也是最容易出问题的地方。HSMS定义了多个超时定时器,每个都有特定的用途。
3.4.1 超时定时器一览
| 定时器 | 默认值 | 用途 |
|---|---|---|
| T3 | 45秒 | 等待回复超时 |
| T5 | 10秒 | 连接建立超时 |
| T6 | 5秒 | 数据发送超时 |
| T7 | 10秒 | 连接断开超时 |
| T8 | 5秒 | 网络空闲超时 |
这些超时值不是随便设的。我见过有人把T3设成5秒,结果设备处理慢一点就超时重传,搞得网络里全是重复消息。也见过有人把T8设成60秒,网络断了1分钟才发现,生产线都停了。
3.4.2 重传机制
HSMS的重传机制很简单:发送消息后启动T3定时器,如果在T3内没收到回复,就重传。重传次数没有硬性规定,但一般建议3-5次。
我个人的做法是:
- 第一次重传:等待T3
- 第二次重传:等待T3 * 1.5
- 第三次重传:等待T3 * 2
- 超过3次:断开连接,报错
为什么要递增等待时间?因为网络拥堵时,频繁重传只会让情况更糟。递增等待时间可以给网络一些恢复的时间。
避坑指南:我曾经遇到过一个问题——设备发送消息后,主机端其实已经处理完了,但回复消息在网络中延迟了。设备端因为T3超时,重传了同样的消息。主机端收到重复消息后,又处理了一次,导致数据重复。解决方案是:在消息ID中加入序列号,主机端根据序列号判断是否重复。
3.5 知识体系总览
下面这张图,是我自己整理的HSMS协议知识体系。你看一眼,就能对整个章节有个全局认识。
这张图把HSMS协议分成了四大块:连接管理、消息格式、会话管理、超时重传。你看,超时重传是贯穿整个协议的,它不是一个独立的功能,而是所有通信的基础保障。
好了,HSMS协议的核心内容就这些。说白了,它就是一套“怎么连、怎么发、怎么断、出错了怎么办”的规矩。你把这些规矩吃透了,写代码时就不会慌。
最后说一句:HSMS协议本身不复杂,复杂的是各种边界情况。我建议你在写代码时,多想想“如果网络断了怎么办”、“如果对方没回复怎么办”、“如果消息重复了怎么办”。把这些异常情况都处理好了,你的系统就稳了。
公众号:蓝海资料掘金营,微信deep3321