KeepAlive 心跳 (C)
C SDK 内置 KeepAlive 心跳: 周期性读 ServerStatus.CurrentTime (i=2258) 做探测, 既维持会话不超时, 又能在第一时间发现连接异常.
前置阅读
- 状态变更回调请看 状态回调.
- 自动重连流程请看 Connect / Disconnect.
配置字段
DarraUa_SessionConfig cfg;
DarraUa_SessionConfig_Init(&cfg);
cfg.keepalive_interval_ms = 5000; /* 5 秒 */
| 项 | 值 |
|---|---|
| 单位 | 毫秒 |
| 默认 | 10000 (10 秒) |
| 最小推荐 | 1000 |
| 0 | 禁用 |
keepalive_interval_ms 只在 DarraUa_Session_Create(&cfg, &h) 时生效, 之后修改 cfg 不影响已创建的句柄. 如要动态改心跳周期, 当前需 Disconnect → 改 cfg → Create 新句柄.
自动启停
| 时机 | 行为 |
|---|---|
Session_Connect 成功后 | 自动启动 (若 keepalive_interval_ms > 0) |
Session_Disconnect | 自动停止 |
| 自动重连成功 | 重新启动 |
心跳事件
C SDK 不暴露独立的 "KeepAlive 事件回调", 心跳失败统一通过 状态回调 反映 — 状态从 CONNECTED 切到 RECONNECTING (开启 auto_reconnect) 或 FAILED.
static void on_state(DarraUa_SessionHandle h, DarraUa_SessionState s,
DarraUa_Status code, void* ctx)
{
if (s == DARRA_UA_SESSION_RECONNECTING)
printf("Heartbeat lost, reconnecting (%s)\n", DarraUa_StatusName(code));
}
DarraUa_Session_SetStateCallback(h, on_state, NULL);
与 SessionTimeout 的关系
服务端 SessionTimeout 默认 10 分钟. 客户端的 KeepAlive 必须比 SessionTimeout 短得多 (推荐 ~1/10), 否则服务端因为 "Session 长时间无活动" 主动 Cleanup, 客户端拿到 BadSessionIdInvalid 才发现.
session_timeout_ms | keepalive_interval_ms 推荐 |
|---|---|
| 600000 (默认 10 分) | 10000 (默认 10 秒) |
| 300000 (5 分钟) | 5000 |
| 3600000 (1 小时) | 30000 |
为什么用 ServerStatus.CurrentTime
OPC UA 没有专门的 KeepAlive 协议消息, 通常的做法是发一个轻量级 Read 请求做心跳. ServerStatus.CurrentTime (i=2258) 是 OPC Foundation 标准节点, 任何符合规范的 Server 都有, Read 开销极小.
自定义心跳逻辑
如果想完全禁用 SDK 内置心跳, 自己实现:
cfg.keepalive_interval_ms = 0; /* 禁用 SDK 内置 */
DarraUa_Session_Create(&cfg, &h);
DarraUa_Session_Connect(h);
/* 自己的线程 */
while (running) {
OPCUA_SLEEP_SEC(5);
if (DarraUa_Session_GetState(h) != DARRA_UA_SESSION_CONNECTED) continue;
DarraUa_Status st = 0;
DarraUa_DataValue* dv = DarraUa_Session_ReadNode(
h, "i=2258", DARRA_UA_ATTR_VALUE, &st);
if (dv) DarraUa_DataValue_Delete(dv);
if (!DARRA_UA_STATUS_IS_GOOD(st)) {
/* 自己处理掉线 */
}
}
性能影响
KeepAlive 每次开销:
- 1 次 Read RPC (网络往返 + 服务端读 + 序列化)
- 典型局域网 ~3-5 ms
- 远程网络 ~50-200 ms
10 秒周期 = ~0.5% CPU / 带宽开销, 完全可忽略.