Session 会话 (C)
C SDK 的 Session 不是对象, 而是 由 DarraUa_SessionHandle (uint32_t) 标识的内部上下文. 所有 DarraUa_Session_* 函数第一个参数都是这个 handle.
声明位于 <opcua/opcua_session.h>, 已被主头 opcua.h 包含.
子页跳转
- 配置结构体字段与默认值请参考 构造与配置.
- 建链 / 断开 / 状态码请参考 Connect / Disconnect.
- 单节点 / 批量读写请参考 Read / Write.
- 状态变更回调请参考 事件回调.
- 命名空间反查请参考 Namespaces.
- 心跳与会话保活请参考 KeepAlive.
句柄类型
typedef uint32_t DarraUa_SessionHandle;
#define UA_INVALID_SESSION_HANDLE 0u
0 是非法值, 所有 _Create 类函数失败时把出参置零, 上层用比较法判失败.
公共配置字段 (DarraUa_SessionConfig)
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 连接 | endpoint_url | const char* | in | OPC UA endpoint, 如 opc.tcp://host:4840 |
security_mode | DarraUa_MessageSecurityMode | in | None / Sign / SignAndEncrypt | |
security_policy_uri | const char* | in | SecurityPolicy URI (#None / #Basic256Sha256) | |
| 登录 | user_token_type | DarraUa_UserTokenType | in | Anonymous / Username / Certificate / Issued |
username | const char* | in | user_token_type=USERNAME 时使用 | |
password | const char* | in | 配 username 用 | |
| 证书 | client_cert_path | const char* | in | 客户端 PFX 路径 (Sign 必填) |
client_key_path | const char* | in | PFX 密码 (字段复用) | |
server_cert_path | const char* | in | 服务端 DER, NULL = TOFU | |
| 超时 | session_timeout_ms | uint32_t | in | 服务端 Session 超时, 默认 600000 (10 分钟) |
connect_timeout_ms | uint32_t | in | 建链超时, 默认 10000 (10 秒) | |
request_timeout_ms | uint32_t | in | 单 RPC 超时, 默认 10000 (10 秒) | |
keepalive_interval_ms | uint32_t | in | 心跳周期, 默认 10000, 0 = 禁用 | |
| 重连 | auto_reconnect | uint32_t | in | 1 = 启用, 0 = 不重连 |
reconnect_max_retries | uint32_t | in | 默认 3 | |
reconnect_delay_ms | uint32_t | in | 默认 2000 |
务必先调 DarraUa_SessionConfig_Init(&cfg) 把所有字段填默认值, 再覆写需要的字段.
完整 API 速查
生命周期
DarraUa_SessionConfig_Init(&cfg)— 填默认值DarraUa_Session_Create(&cfg, &h)— 创建句柄 (尚未连接)DarraUa_Session_Connect(h)— Hello → SecureChannel → Session → ActivateDarraUa_Session_Disconnect(h)— 主动断开, 句柄保留可重连DarraUa_Session_Close(h)— 关闭并释放句柄
状态
DarraUa_Session_GetState(h)— 返回DarraUa_SessionState枚举DarraUa_Session_SetStateCallback(h, cb, ctx)— 注册状态变更回调
读 / 写
DarraUa_Session_ReadNode(h, "i=2258", attr, &st)— 字符串 NodeId 单节点读DarraUa_Session_Read(h, items, n, out_dvs)— 批量读 (结构体数组)DarraUa_Session_ReadNodes(h, ids, attrs, n, out_dvs)— 批量读 (字符串数组)DarraUa_Session_WriteNode(h, "ns=2;s=X", attr, v)— 字符串 NodeId 单节点写DarraUa_Session_Write(h, items, n, out_results)— 批量写
浏览 / 路径解析
DarraUa_Session_BrowseNode(h, "i=84", filter, &res)— 单节点 (字符串)DarraUa_Session_Browse(h, &node_id, filter, &res)— 单节点 (结构体)DarraUa_Session_BrowseNodes(h, ids, n, filter, results)— 批量浏览DarraUa_Session_BrowseNext(h, release, cp, cp_len, &res)— 续翻分页DarraUa_Session_TranslateBrowsePaths(h, ...)— 路径批量解析DarraUa_Session_ResolveBrowsePath(h, start, path, buf, bufSz)— 单条相对路径解析DarraUa_Session_RegisterNodes(h, ids, n, &out)— 注册临时高效 NodeIdDarraUa_Session_UnregisterNodes(h, ids, n)— 注销
命名空间
DarraUa_Session_LoadNamespaceArray(h)— 强制重读 i=2255DarraUa_Session_GetNamespaceCount(h)— 命名空间数DarraUa_Session_GetNamespaceUri(h, idx)— URI 查询DarraUa_Session_FindNamespaceIndex(h, uri)— 反查 URI → Index
订阅
DarraUa_Subscription_Create(h, &cfg, &sub)— 创建数据订阅DarraUa_Session_Publish(h, timeout_ms)— 手动 PumpDarraUa_Session_StartAutoPublish(h)/_Stop— 后台 Publish 线程DarraUa_Session_TransferSubscriptions(...)— 跨 Session 迁移订阅
方法 / 历史
DarraUa_Session_Call(h, &obj, &method, args, n, &out, &nout, &st)— Call OPC UA MethodDarraUa_Session_HistoryRead*(...)— 5 模式 HistoryReadDarraUa_Session_HistoryUpdateData / HistoryDeleteRange— 写 / 删历史
控制
DarraUa_Session_Cancel(h, request_handle, &cancelled_count)— 取消未完成请求
状态机
typedef enum {
UA_SESSION_DISCONNECTED = 0,
UA_SESSION_CONNECTING = 1,
UA_SESSION_CONNECTED = 2,
UA_SESSION_RECONNECTING = 3,
UA_SESSION_CLOSING = 4,
UA_SESSION_FAILED = 5
} DarraUa_SessionState;
调用流向:
Disconnected
↓ Session_Connect
Connecting
↓
Connected
↓ (网络异常 + auto_reconnect=1)
Reconnecting
├── 成功 → Connected
└── 失败 → Failed → Closing → Disconnected
完整示例
#include <opcua/opcua.h>
#include <stdio.h>
#if defined(_WIN32)
# include <windows.h>
# define OPCUA_SLEEP_SEC(s) Sleep((s) * 1000)
#else
# include <unistd.h>
# define OPCUA_SLEEP_SEC(s) sleep(s)
#endif
static void on_state(DarraUa_SessionHandle h, DarraUa_SessionState st,
DarraUa_Status code, void* ctx)
{
(void)h; (void)ctx;
printf("Session state -> %d (status 0x%08X)\n", (int)st, (unsigned)code);
}
int main(int argc, char** argv)
{
const char* endpoint = (argc >= 2) ? argv[1] : "opc.tcp://localhost:4840";
DarraUa_Initialize();
DarraUa_SessionConfig cfg;
DarraUa_SessionConfig_Init(&cfg);
cfg.endpoint_url = endpoint;
cfg.security_mode = UA_MSG_SECURITY_MODE_NONE;
cfg.security_policy_uri = "http://opcfoundation.org/UA/SecurityPolicy#None";
cfg.user_token_type = UA_USER_TOKEN_ANONYMOUS;
DarraUa_SessionHandle h = UA_INVALID_SESSION_HANDLE;
if (!UA_STATUS_IS_GOOD(DarraUa_Session_Create(&cfg, &h))) goto cleanup;
DarraUa_Session_SetStateCallback(h, on_state, NULL);
if (!UA_STATUS_IS_GOOD(DarraUa_Session_Connect(h))) goto cleanup;
/* Read */
DarraUa_Status st = 0;
DarraUa_DataValue* dv = DarraUa_Session_ReadNode(
h, "i=2258", UA_ATTR_VALUE, &st);
if (dv) {
DarraUa_DateTime ft = DarraUa_Variant_GetDateTime(
DarraUa_DataValue_GetValue(dv));
printf("CurrentTime ft=%lld\n", (long long)ft);
DarraUa_DataValue_Delete(dv);
}
cleanup:
if (h) {
DarraUa_Session_Disconnect(h);
DarraUa_Session_Close(h);
}
DarraUa_Shutdown();
return 0;
}