模块契约网络 Framing API

线程

帧解析器为调用方栈上的值对象,无共享状态;解析与帧操作可任意线程并发调用(不同解析器实例之间与同一实例的顺序调用均安全,实例本身非多线程共享)。

错误

  • XNET_ERROR_FRAME_CONFIG:配置本身不可能形成合法帧。
  • XNET_ERROR_FRAME_STATE:Framer 或帧范围已失效。
  • XNET_ERROR_FRAME_LIMIT:完整帧或行 payload 超过硬上限。
  • XNET_ERROR_FRAME_LENGTH:声明长度、调整或本机长度转换溢出。

MORE 是正常增量控制结果,不设置错误。ERROR 保留结构化错误;调用方通常应关闭当前协议流或按协议定义丢弃输入后重置 Framer。

分层与裁剪

  • XRT_FEATURE_NET_FRAME:统一帧描述、payload 复制和精确消费,只依赖 NET_BUFFER。
  • XRT_FEATURE_NET_FRAME_LINE:任意长度分隔符的增量行 framing,只依赖 NET_FRAME。
  • XRT_FEATURE_NET_FRAME_LENGTH:1 到 8 字节长度字段 framing,只依赖 NET_FRAME。

HTTP/1 和 WebSocket 有各自的协议状态机,不经过通用 framing vtable。这里用于 TCP 上的文本协议、长度前缀 RPC、自定义消息协议和协议探测层。

通用帧

帧只借用当前 xnetbuf。PayloadOffset 和 FrameSize 都相对缓冲头部;输入前缀被消费、替换或重排后,调用方不得继续使用旧帧。xrtNetFrameCopy 最多复制输出容量个 payload 字节,适合小消息便利路径;零拷贝用户可直接使用 xrtNetBufSpans、xrtNetBufPeek 和偏移。xrtNetFrameConsume 会验证当前输入仍能完整容纳该范围,再精确消费 FrameSize 字节。

行分隔帧

xrtNetLineConfigInit 默认使用 LF、8192 字节 payload 上限并从 payload 去除分隔符。Delimiter 是借用视图,没有固定长度上限,必须在 Framer 使用期间保持存活且内容不变。MaxPayload 只限制分隔符之前的字节;需要无界模式时显式设为 SIZE_MAX。

xrtNetLineNext 返回 MORE 后,调用方只能保留原输入前缀并在同一个 xnetbuf 尾部追加;消费、替换、换用另一缓冲或重排输入前应调用 xrtNetLineReset。Framer 保存块指针、块内偏移和未决候选位置,因此即使逐次追加大量单字节引用块,也不会为定位旧偏移反复遍历链头。分隔符跨缓冲块、自重叠和位于 payload 上限的情况都受支持;分隔符开始位置超过上限立即返回 XNET_FRAME_ERROR 和 XNET_ERROR_FRAME_LIMIT。

完整示例位于 examples/network/frame_line/main.c。

长度前缀帧

帧总长按以下公式计算:

LengthSize 支持 1 到 8 字节,Order 明确选择大小端。Strip 指定 payload 起点,可以保留完整头部、只去除长度字段,或去除应用头。若协议长度字段已经包含头部,可使用负 Adjustment。所有字段末端、无符号声明值、有符号调整、size_t 转换、strip 和 MaxFrame 都在访问 payload 前验证。

默认配置是四字节大端 payload 长度、去除四字节字段和 1 MiB 总帧上限。完整示例位于 examples/network/frame_length/main.c。

xnetframestatus类型

增量 framing 只区分失败、等待更多字节和完整帧。

值语义
XNET_FRAME_ERROR失败
XNET_FRAME_MORE需要更多输入
XNET_FRAME_READY已解析完整帧
typedef enum xnetframestatus { XNET_FRAME_ERROR = -1, XNET_FRAME_MORE = 0, XNET_FRAME_READY = 1 } xnetframestatus;

xnetframe类型

所有偏移都相对当前输入头部,Declared 保存协议字段原值。

字段类型语义
PayloadOffsetsize_tPayloadOffset
PayloadSizesize_tPayloadSize
FrameSizesize_tFrameSize
Declareduint64Declared
typedef struct xnetframe { size_t PayloadOffset; size_t PayloadSize; size_t FrameSize; uint64 Declared; } xnetframe;

xnetlineconfig类型

分隔符只借用调用方字节,并且必须存活到 Framer 不再使用。

字段类型语义
Delimiterxbytesview分隔符
MaxPayloadsize_tMaxPayload
IncludeDelimiterboolIncludeDelimiter
typedef struct xnetlineconfig { xbytesview Delimiter; size_t MaxPayload; bool IncludeDelimiter; } xnetlineconfig;

xnetlineframer类型

Line Framer 保存块内增量游标,字段公开只用于无分配栈存储。

字段类型语义
Configxnetlineconfig配置
Inputconst xnetbuf*输入视图
Cursorxnetblock*Cursor
CursorOffsetsize_tCursorOffset
Searchsize_tSearch
PreviousSizesize_tPreviousSize
Guarduint32守卫字(防误用)
typedef struct xnetlineframer { xnetlineconfig Config; const xnetbuf* Input; xnetblock* Cursor; size_t CursorOffset; size_t Search; size_t PreviousSize; uint32 Guard; } xnetlineframer;

xnetframeorder类型

长度字段字节序独立于主机字节序。

值语义
XNET_FRAME_BIG_ENDIANXNETFRAMEBIGENDIAN
XNET_FRAME_LITTLE_ENDIAN小端字节序
typedef enum xnetframeorder { XNET_FRAME_BIG_ENDIAN = 0, XNET_FRAME_LITTLE_ENDIAN = 1 } xnetframeorder;

xnetlengthconfig类型

FrameSize = LengthOffset + LengthSize + Declared + Adjustment。

字段类型语义
LengthOffsetsize_tLengthOffset
LengthSizesize_tLengthSize
Adjustmentint64Adjustment
Stripsize_tStrip
MaxFramesize_tMaxFrame
Orderxnetframeorder字节序
typedef struct xnetlengthconfig { size_t LengthOffset; size_t LengthSize; int64 Adjustment; size_t Strip; size_t MaxFrame; xnetframeorder Order; } xnetlengthconfig;

xnetlengthframer类型

Length Framer 复制并验证配置,解析本身不保存输入状态。

字段类型语义
Configxnetlengthconfig配置
Guarduint32守卫字(防误用)
typedef struct xnetlengthframer { xnetlengthconfig Config; uint32 Guard; } xnetlengthframer;
通用帧

xrtNetFrameCopy函数

从完整帧复制不超过输出容量的 payload 字节,返回实际复制数。

size_t xrtNetFrameCopy(const xnetbuf* pInput, const xnetframe* pFrame, void* pOutput, size_t iCapacity)

参数

参数方向约束说明
pInput输入非空帧所在的输入缓冲
pFrame输入非空Next 产出的帧描述
pOutput输出容量非零时非空接收 payload
iCapacity输入—输出容量
返回值
返回含义失败时状态
>= 0实际复制字节数(不超过 payload 与容量的较小者);0 = 失败或空 payloadXERR_ARGUMENT 等
错误
  • XERR_ARGUMENT — 指针为空,或容量非零但输出为空
  • xrt.net / XNET_ERROR_FRAME_STATE(XERR_STATE) — 帧范围越出当前输入头部

范例已编译验证

frame_line · 复制 payload

		size_t iSize = xrtNetFrameCopy(
			&Input, &Frame, sLine, sizeof(sLine) - 1u
		);

xrtNetFrameConsume函数

只有帧范围仍完整位于输入头部时才精确消费 FrameSize 字节。

bool xrtNetFrameConsume(xnetbuf* pInput, const xnetframe* pFrame)

参数

参数方向约束说明
pInput输入/输出非空要消费的输入缓冲
pFrame输入非空Next 产出的帧描述
返回值
返回含义失败时状态
true已从输入头部移除整帧—
false帧越出当前输入XERR_STATE 域错误
错误
  • XERR_ARGUMENT — 指针为空
  • xrt.net / XNET_ERROR_FRAME_STATE(XERR_STATE) — 帧范围越出当前输入头部

范例已编译验证

frame_line · 消费帧

		if ( !xrtNetFrameConsume(&Input, &Frame) ) {
行分隔帧

xrtNetLineConfigInit函数

初始化 LF 分隔、8192 字节 payload 上限和去除分隔符的默认配置。

void xrtNetLineConfigInit(xnetlineconfig* pConfig)

参数

参数方向约束说明
pConfig输出非空接收配置
返回值
返回含义失败时状态
无已初始化—
错误
  • 无 — 初始化不失败

范例已编译验证

frame_line · 默认配置

	xrtNetLineConfigInit(&Config);

xrtNetLineInit函数

复制配置并开始一条新的增量行帧搜索。

bool xrtNetLineInit(xnetlineframer* pFramer, const xnetlineconfig* pConfig)

参数

参数方向约束说明
pFramer输出非空接收搜索器
pConfig输入非空行帧配置
返回值
返回含义失败时状态
true已初始化—
false配置非法xrt.net 域错误
错误
  • xrt.net / XNET_ERROR_FRAME_CONFIG(XERR_ARGUMENT) — 分隔符为空、上限为 0 或成员组合非法

范例已编译验证

frame_line · 初始化

	if ( !xrtNetLineInit(&Framer, &Config) ||
		 !xrtNetBufInit(&Input, NULL) ||
		 !xrtNetBufAppend(&Input, "first\r", 6) ) {

xrtNetLineReset函数

保留配置并丢弃当前增量搜索进度。

bool xrtNetLineReset(xnetlineframer* pFramer)

参数

参数方向约束说明
pFramer输入/输出已初始化目标搜索器
返回值
返回含义失败时状态
true进度已清空,配置保留—
false搜索器状态非法XERR_STATE 域错误
错误
  • xrt.net / XNET_ERROR_FRAME_STATE(XERR_STATE) — 搜索器未初始化或守卫字被破坏

范例已编译验证

frame_line · 重置进度

	(void)xrtNetLineReset(&Framer);

xrtNetLineNext函数

解析输入头部的下一条分隔帧;返回 MORE 后只允许保留前缀并追加输入。

xnetframestatus xrtNetLineNext(xnetlineframer* pFramer, const xnetbuf* pInput, xnetframe* pFrame)

参数

参数方向约束说明
pFramer输入/输出已初始化目标搜索器
pInput输入非空输入缓冲(MORE 后须保留未决前缀)
pFrame输出非空接收帧描述
返回值
返回含义失败时状态
XNET_FRAME_READY已解析一条完整帧,pFrame 有效—
XNET_FRAME_MORE输入不足,需保留未决前缀并追加数据不设错误
XNET_FRAME_ERROR参数非法、状态破坏或帧超限XERR_ARGUMENT / xrt.net 域错误
错误
  • XERR_ARGUMENT — 指针为空
  • xrt.net / XNET_ERROR_FRAME_STATE(XERR_STATE) — 搜索器状态非法或违反 MORE 后的前缀保留契约
  • xrt.net / XNET_ERROR_FRAME_LIMIT(XERR_RANGE) — 行 payload 超过配置上限

范例已编译验证

frame_line · 解析下一行

	if ( xrtNetLineNext(&Framer, &Input, &Frame) != XNET_FRAME_MORE ||
		 !xrtNetBufAppend(&Input, "\nsecond\r\n", 10) ) {
长度前缀帧

xrtNetLengthConfigInit函数

初始化四字节大端长度、去除长度字段和 1 MiB 帧上限的默认配置。

void xrtNetLengthConfigInit(xnetlengthconfig* pConfig)

参数

参数方向约束说明
pConfig输出非空接收配置
返回值
返回含义失败时状态
无已初始化—
错误
  • 无 — 初始化不失败

范例已编译验证

frame_length · 默认配置

	xrtNetLengthConfigInit(&Config);

xrtNetLengthInit函数

复制并验证长度字段偏移、宽度、字节序、调整值、strip 和帧上限。

bool xrtNetLengthInit(xnetlengthframer* pFramer, const xnetlengthconfig* pConfig)

参数

参数方向约束说明
pFramer输出非空接收搜索器
pConfig输入非空长度前缀配置
返回值
返回含义失败时状态
true已初始化—
false配置非法xrt.net 域错误
错误
  • xrt.net / XNET_ERROR_FRAME_CONFIG(XERR_ARGUMENT) — 偏移 + 宽度、调整值或上限组合非法

范例已编译验证

frame_length · 初始化

	if ( !xrtNetLengthInit(&Framer, &Config) ||
		 !xrtNetBufInit(&Input, NULL) ||
		 !xrtNetBufAppend(&Input, Packet, sizeof(Packet)) ||
		 (xrtNetLengthNext(&Framer, &Input, &Frame) !=
			XNET_FRAME_READY) ||
		 (xrtNetFrameCopy(
			&Input, &Frame, sPayload, sizeof(sPayload) - 1u
		 ) != 5) ) {

xrtNetLengthNext函数

从输入头部解析下一条长度前缀帧。

xnetframestatus xrtNetLengthNext(const xnetlengthframer* pFramer, const xnetbuf* pInput, xnetframe* pFrame)

参数

参数方向约束说明
pFramer输入/输出已初始化目标搜索器
pInput输入非空输入缓冲
pFrame输出非空接收帧描述
返回值
返回含义失败时状态
XNET_FRAME_READY已解析一条完整帧,pFrame 有效—
XNET_FRAME_MORE输入不足,需保留未决前缀并追加数据不设错误
XNET_FRAME_ERROR参数非法、状态破坏或帧超限XERR_ARGUMENT / xrt.net 域错误
错误
  • XERR_ARGUMENT — 指针为空
  • xrt.net / XNET_ERROR_FRAME_STATE(XERR_STATE) — 搜索器状态非法或长度字段越出输入
  • xrt.net / XNET_ERROR_FRAME_LENGTH(XERR_RANGE / XERR_VALUE) — 声明长度溢出、超过上限或调整后非法

范例已编译验证

frame_length · 解析下一帧

		 (xrtNetLengthNext(&Framer, &Input, &Frame) !=
			XNET_FRAME_READY) ||

常量索引常量

以下常量在本页所属头文件中定义,语义见公共头注释。

常量说明
XNET_FRAME_BIG_ENDIAN见头文件注释
XNET_FRAME_ERROR见头文件注释
XNET_FRAME_LITTLE_ENDIAN见头文件注释
XNET_FRAME_MORE见头文件注释
XNET_FRAME_READY见头文件注释