跳到主要内容

KeepAlive 心跳 (C)

C SDK 内置 KeepAlive 心跳: 周期性读 ServerStatus.CurrentTime (i=2258) 做探测, 既维持会话不超时, 又能在第一时间发现连接异常.

前置阅读

配置字段

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_mskeepalive_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 / 带宽开销, 完全可忽略.

下一步