一个可靠连接要处理的四件事
- 检测:怎么知道连接断了
- 重连:用什么节奏重新连接
- 呈现:断线期间界面/数据怎么表现
- 恢复:重连成功后怎么补齐、回到正常状态
检测:读超时 + 心跳双保险
- 操作超时:每次读写设超时,超时计一次失败
- 心跳探测:周期读一个固定点,判断链路是否活着
- 失败计数:连续 N 次失败才判定断线,避免一次偶发抖动就误判、误切换状态
重连:指数退避,不要疯狂重连
断线后如果用 while(true) 立刻重连,网络故障时会打爆设备和网络。正确做法是指数退避:
第1次:等待 1s
第2次:等待 2s
第3次:等待 4s
第4次:等待 8s
……封顶 30s
连接成功后重置间隔。这样既恢复及时,又不会在故障时制造额外压力。
用连接状态机管理
已连接 → (连续失败N次) → 断线中 → (退避计时) → 重连中 → 成功 → 已连接
状态机让逻辑清晰、避免多线程下重复发起连接(要加锁,保证同一时刻只有一个重连动作)。
断线期间怎么呈现
- 相关点位标记“坏质量”,状态灯转灰色(区别于数值为 0)
- 界面顶部显示“设备通讯中断”提示
- 停止下发控制指令(断线时写操作应直接拒绝或排队)
- 如有本地缓存能力,采集侧进入断网缓存模式
恢复后做什么
- 重新订阅/刷新一次全量点位(避免用断线期间的旧值)
- 清除坏质量标记,状态灯恢复
- 若启用了断网缓存,把缓存数据补传入库(带原始时间戳)
- 记录一次断线/恢复日志,便于统计通讯可用率
跨协议通用
无论 Modbus、MC、S7 还是 OPC UA、MQTT,这套“超时检测—失败计数—指数退避—状态机—恢复补齐”的骨架完全通用,差异只在具体的连接 API。把它做进驱动基类,所有协议驱动复用,系统的通讯可靠性会有质的提升。