自动重连
概述
OPC UA Server 维护重启 / 网络抖动时 Session 失效。SDK 内部把所有 RPC 都包了一层重试机制:
- 调底层 RPC, 命中
BadSessionClosed/BadSessionIdInvalid/BadSecureChannelClosed - 自动调
Reconnect重建 SecureChannel + Session - 重连成功重试一次
- 仍失败 → 返回标准
Bad*StatusCode
业务侧无需处理, 重连结果通过事件回调通知。
API
| 函数 / 回调 | 类别 | 读写 | 说明 |
|---|---|---|---|
| DarraUa_Session_Reconnect(ua) | 方法 | 写 | 手动触发重连 |
| DarraUa_RegisterReconnectingHandler(ua, cb, ctx) | 事件 | 读 | 重连开始 |
| DarraUa_RegisterReconnectedHandler(ua, cb, ctx) | 事件 | 读 | 重连成功 |
| DarraUa_RegisterDisconnectedHandler(ua, cb, ctx) | 事件 | 读 | 断开 |
| DarraUa_RegisterSessionLostHandler(ua, cb, ctx) | 事件 | 读 | Session 失效预警 |
回调签名: void cb(const DarraUa_EventEntry* e, void* ctx)。
代码示例
#include <opcua.h>
void on_reconnecting(const DarraUa_EventEntry* e, void* ctx) {
printf("重连中... %s\n", e->source);
}
void on_reconnected(const DarraUa_EventEntry* e, void* ctx) {
printf("已恢复\n");
}
void on_session_lost(const DarraUa_EventEntry* e, void* ctx) {
fprintf(stderr, "Session 失效: %s (0x%08X)\n", e->message, e->status_code);
}
int main() {
DarraUa_Session* ua;
DarraUa_Session_New("opc.tcp://localhost:4840", &ua);
DarraUa_RegisterReconnectingHandler(ua, on_reconnecting, NULL);
DarraUa_RegisterReconnectedHandler(ua, on_reconnected, NULL);
DarraUa_RegisterSessionLostHandler(ua, on_session_lost, NULL);
DarraUa_Session_Connect(ua);
// 业务代码完全不需要处理重连
while (running) {
DarraUa_DataValue* dv = NULL;
DarraUa_Session_ReadSafe(ua, "ns=2;s=Temp", ATTR_VALUE, &dv);
if (dv) DarraUa_FreeDataValue(dv);
// 即使中途服务端重启, ReadSafe 已自动重连+重试
sleep(1);
}
DarraUa_Session_Free(ua);
return 0;
}
重连策略
- 单次 RPC 最多重连 1 次
- 重连超时 =
DarraUa_Session_New时的connect_timeout_ms(默认 10000) - 多 RPC 并发触发时内部串行化
- 完全失败由业务侧通过 disconnected 事件提示用户
与订阅自恢复
Session 重连后 SDK 自动:
- 尝试
DarraUa_Session_TransferSubscriptions(old_sub_id)转移 - 失败 → 用缓存的 MonitoredItemSpec 重建全部 MI
详见 订阅自恢复。
跨语言对照
| C# | Python | Java | C++ | Rust | C |
|---|---|---|---|---|---|
| ua.Reconnect() | ua.reconnect() | ua.reconnect() | ua.Reconnect() | ua.reconnect() | DarraUa_Session_Reconnect |