BrowseNext (C)
当 Browse 返回的子节点超过服务端单页限制时, 服务端在 BrowseResult 里返回非空的 ContinuationPoint (续翻凭证). 用 BrowseNext 继续拿下一页.
前置阅读
- 想拿到 ContinuationPoint 必须先
Browse, 然后调_GetContinuationPoint, 见 Browse. - 想直接拿全部子节点的封装模板请看 Browse 自动分页.
API
DARRA_OPCUA_API DarraUa_Status DARRA_OPCUA_CALL DarraUa_Session_BrowseNext(
DarraUa_SessionHandle h,
int32_t release_continuation_points, /* 1 = release, 0 = continue */
const uint8_t* continuation_point,
int32_t continuation_point_len,
DarraUa_BrowseResult** out_result);
DARRA_OPCUA_API const uint8_t* DARRA_OPCUA_CALL
DarraUa_BrowseResult_GetContinuationPoint(
const DarraUa_BrowseResult* r, int32_t* out_len);
| 参数 | 说明 |
|---|---|
release_continuation_points | 1 = 放弃续翻, 服务端释放资源 (不返回 references) |
continuation_point / _len | 上一次 BrowseResult 给的续翻凭证 |
out_result | 出参, 含本页 references + 新的 ContinuationPoint |
_GetContinuationPoint 返回的指针指向 BrowseResult 内部缓冲, 不要 free, 且 BrowseResult_Delete 后失效. 如要保留请自行拷贝.
完整翻页例子
#include <darra_opcua/darra_opcua.h>
#include <stdio.h>
#include <string.h>
static void browse_all(DarraUa_SessionHandle h, const char* root)
{
DarraUa_BrowseResult* page = NULL;
DarraUa_Status st = DarraUa_Session_BrowseNode(
h, root, DARRA_UA_NODE_CLASS_UNSPECIFIED, &page);
if (!DARRA_UA_STATUS_IS_GOOD(st) || !page) return;
uint32_t total = 0;
char id_buf[128];
while (page) {
uint32_t n = DarraUa_BrowseResult_GetCount(page);
for (uint32_t i = 0; i < n; ++i) {
const DarraUa_ReferenceDescription* rd =
DarraUa_BrowseResult_GetReference(page, i);
DarraUa_Ref_GetNodeIdString(rd, id_buf, (int32_t)sizeof(id_buf));
printf(" %s\n", id_buf);
}
total += n;
/* 拿续翻凭证, 拷贝出来 (因为 page_Delete 会失效) */
int32_t cp_len = 0;
const uint8_t* cp = DarraUa_BrowseResult_GetContinuationPoint(page, &cp_len);
if (!cp || cp_len <= 0) {
DarraUa_BrowseResult_Delete(page);
break;
}
uint8_t cp_copy[256]; /* 服务端一般 < 64 字节 */
if (cp_len > (int32_t)sizeof(cp_copy)) {
DarraUa_BrowseResult_Delete(page);
break; /* 异常长度, 放弃 */
}
memcpy(cp_copy, cp, (size_t)cp_len);
DarraUa_BrowseResult_Delete(page);
/* 翻下一页 */
page = NULL;
DarraUa_Session_BrowseNext(
h, /*release*/ 0, cp_copy, cp_len, &page);
}
printf("Total %u children\n", (unsigned)total);
}
主动释放 (节省服务端资源)
服务端为每个 ContinuationPoint 维护状态, 占用资源. 如果中途不想继续翻, 调 release=1 显式释放:
DarraUa_Session_BrowseNext(h, /*release*/ 1, cp_copy, cp_len, NULL);
否则服务端会在超时后 (典型 5 分钟) 自动 GC.
注意
ContinuationPoint是不透明字节数组, 不要修改 / 解析- 同一个 ContinuationPoint 只能用一次 (用完无效)
- 服务端 ContinuationPoint 数量上限 (通常每 Session ~10-100), 超过后旧 CP 会被踢
- 翻页期间不要
Disconnect, CP 会失效