跳到主要内容

配置与创建 (C)

C SDK 用 结构体 + 函数 替代 C# 的多重载构造函数. 流程:

  1. 声明 DarraUa_SessionConfig cfg;
  2. DarraUa_SessionConfig_Init(&cfg) 填默认值
  3. 覆写需要修改的字段
  4. DarraUa_Session_Create(&cfg, &handle) 创建句柄
  5. 用完调 DarraUa_Session_Close(handle) 释放
前置阅读

DarraUa_SessionConfig 字段详解

typedef struct {
const char* endpoint_url;
DarraUa_MessageSecurityMode security_mode;
const char* security_policy_uri;
DarraUa_UserTokenType user_token_type;
const char* username;
const char* password;
const char* client_cert_path;
const char* client_key_path;
const char* server_cert_path;
uint32_t session_timeout_ms;
uint32_t connect_timeout_ms;
uint32_t request_timeout_ms;
uint32_t keepalive_interval_ms;
uint32_t auto_reconnect;
uint32_t reconnect_max_retries;
uint32_t reconnect_delay_ms;
} DarraUa_SessionConfig;
类别属性类型访问说明
必填endpoint_urlconst char*inUTF-8, opc.tcp://host:port. 字符串内存由调用方管理, 必须在 Connect 之前保持有效
安全security_modeDarraUa_MessageSecurityModein默认 NONE
security_policy_uriconst char*in默认 #None; 推荐 #Basic256Sha256
client_cert_pathconst char*in客户端 PFX (Sign / SignAndEncrypt 必填)
client_key_pathconst char*inPFX 密码 (字段复用)
server_cert_pathconst char*in服务端 DER, NULL = TOFU
登录user_token_typeDarraUa_UserTokenTypein默认 ANONYMOUS
usernameconst char*inuser_token_type=USERNAME 时必填
passwordconst char*in配 username 用
超时session_timeout_msuint32_tin服务端 Session 超时, 默认 600000 (10 分钟)
connect_timeout_msuint32_tin建链超时, 默认 10000
request_timeout_msuint32_tin单 RPC 超时, 默认 10000
keepalive_interval_msuint32_tin心跳周期, 默认 10000, 0 = 禁用
重连auto_reconnectuint32_tin1 = 启用 (默认), 0 = 不重连
reconnect_max_retriesuint32_tin默认 3
reconnect_delay_msuint32_tin默认 2000

DarraUa_MessageSecurityMode

typedef enum {
DARRA_UA_MSG_SECURITY_MODE_INVALID = 0,
DARRA_UA_MSG_SECURITY_MODE_NONE = 1,
DARRA_UA_MSG_SECURITY_MODE_SIGN = 2,
DARRA_UA_MSG_SECURITY_MODE_SIGN_ENCRYPT = 3
} DarraUa_MessageSecurityMode;

DarraUa_UserTokenType

typedef enum {
DARRA_UA_USER_TOKEN_ANONYMOUS = 0,
DARRA_UA_USER_TOKEN_USERNAME = 1,
DARRA_UA_USER_TOKEN_CERTIFICATE = 2,
DARRA_UA_USER_TOKEN_ISSUED = 3
} DarraUa_UserTokenType;

常用 SecurityPolicy URI

模式URI
无加密http://opcfoundation.org/UA/SecurityPolicy#None
Basic256Sha256 (推荐)http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256
Aes128_Sha256_RsaOaephttp://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep
Aes256_Sha256_RsaPsshttp://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss

DarraUa_Session_Create

DARRA_OPCUA_API DarraUa_Status DARRA_OPCUA_CALL DarraUa_Session_Create(
const DarraUa_SessionConfig* cfg,
DarraUa_SessionHandle* out_handle);
参数说明
cfg已 Init + 覆写的配置
out_handle出参, 成功后写入有效句柄, 失败置 0
返回含义
DARRA_UA_STATUS_GOOD成功
DARRA_UA_STATUS_INVALID_ARGUMENTcfg=NULL 或 endpoint_url=NULL
DARRA_UA_STATUS_NOT_INITIALIZED没先调 DarraUa_Initialize()
DARRA_UA_STATUS_OUT_OF_MEMORY内部分配失败
DARRA_UA_STATUS_BAD_TCP_ENDPOINT_URL_INVALIDURL 格式不对

_Create 只是创建本地上下文, 不发起任何网络请求. 真正联网发生在 _Connect.


三种典型配置示例

#include <darra_opcua/darra_opcua.h>
#include <stdio.h>

/* 1. 匿名 + 明文 (开发期) */
static int demo_anonymous_no_security(const char* endpoint)
{
DarraUa_SessionConfig cfg;
DarraUa_SessionConfig_Init(&cfg);
cfg.endpoint_url = endpoint;
cfg.security_mode = DARRA_UA_MSG_SECURITY_MODE_NONE;
cfg.security_policy_uri = "http://opcfoundation.org/UA/SecurityPolicy#None";
cfg.user_token_type = DARRA_UA_USER_TOKEN_ANONYMOUS;

DarraUa_SessionHandle h = DARRA_UA_INVALID_SESSION_HANDLE;
DarraUa_Status st = DarraUa_Session_Create(&cfg, &h);
if (!DARRA_UA_STATUS_IS_GOOD(st)) {
fprintf(stderr, "Create failed: 0x%08X (%s)\n",
(unsigned)st, DarraUa_StatusName(st));
return -1;
}
DarraUa_Session_Close(h);
return 0;
}

/* 2. 匿名 + Sign (内网生产) */
static int demo_anonymous_sign(const char* endpoint, const char* pfx)
{
DarraUa_SessionConfig cfg;
DarraUa_SessionConfig_Init(&cfg);
cfg.endpoint_url = endpoint;
cfg.security_mode = DARRA_UA_MSG_SECURITY_MODE_SIGN;
cfg.security_policy_uri = "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256";
cfg.user_token_type = DARRA_UA_USER_TOKEN_ANONYMOUS;
cfg.client_cert_path = pfx;
cfg.client_key_path = "123456";

DarraUa_SessionHandle h = DARRA_UA_INVALID_SESSION_HANDLE;
if (!DARRA_UA_STATUS_IS_GOOD(DarraUa_Session_Create(&cfg, &h))) return -1;
DarraUa_Session_Close(h);
return 0;
}

/* 3. 用户名 + SignAndEncrypt (典型生产) */
static int demo_username_sign_encrypt(const char* endpoint, const char* pfx,
const char* user, const char* pass)
{
DarraUa_SessionConfig cfg;
DarraUa_SessionConfig_Init(&cfg);
cfg.endpoint_url = endpoint;
cfg.security_mode = DARRA_UA_MSG_SECURITY_MODE_SIGN_ENCRYPT;
cfg.security_policy_uri = "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256";
cfg.user_token_type = DARRA_UA_USER_TOKEN_USERNAME;
cfg.username = user;
cfg.password = pass;
cfg.client_cert_path = pfx;
cfg.client_key_path = "123456";
cfg.session_timeout_ms = 1800000; /* 30 分钟 */
cfg.keepalive_interval_ms = 5000; /* 5 秒, 更敏感的断线检测 */

DarraUa_SessionHandle h = DARRA_UA_INVALID_SESSION_HANDLE;
if (!DARRA_UA_STATUS_IS_GOOD(DarraUa_Session_Create(&cfg, &h))) return -1;
DarraUa_Session_Close(h);
return 0;
}

常见坑

  • 未调 DarraUa_SessionConfig_Init: 字段含未定义值, Connect 时大概率 BadConfigurationError
  • endpoint_url 字符串过早释放: 字符串 lifetime 必须覆盖整个 Session 生命周期 (Stack 不会拷贝)
  • 客户端证书路径含中文 / 空格: 路径一律用 ASCII
  • 重连参数太激进: reconnect_max_retries 太大 + 网络抖动会无限重连, 建议 ≤ 5

资源管理

句柄必须用 DarraUa_Session_Close(h) 关闭, 否则 native 上下文泄漏:

DarraUa_SessionHandle h = DARRA_UA_INVALID_SESSION_HANDLE;
DarraUa_Status st = DarraUa_Session_Create(&cfg, &h);
if (!DARRA_UA_STATUS_IS_GOOD(st)) goto cleanup;

st = DarraUa_Session_Connect(h);
/* ... 业务 ... */

DarraUa_Session_Disconnect(h); /* 可选, Close 内部会先 Disconnect */

cleanup:
if (h != DARRA_UA_INVALID_SESSION_HANDLE) {
DarraUa_Session_Close(h);
}

下一步