Skip to main content

传输帧规范

本文档定义 KnotLink 协议在 TCP 链路上的 二进制帧结构。帧头负责定界和版本识别,消息体使用 KLUDF 格式(详见 消息体规范)。


帧结构

每帧由一个 8 字节定长帧头 和一个 变长消息体 组成,大端序(Big Endian):

 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Magic (2) | Version (2) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length (4) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Payload (变长) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
偏移字段大小类型说明
0Magic2 字节uint160x4B4B魔数,固定值 "KK"(ASCII),用于识别 KnotLink 帧
2Version2 字节uint160x0002协议版本号,接收端校验不匹配时告警
4Length4 字节uint321 ~ 16,777,215Payload 的字节数,不含帧头。最大 16 MB
8Payload变长消息体,KLUDF 键值对格式

字段说明

Magic(魔数)

固定值 0x4B4B。两个字节的 ASCII 恰好是 "KK"(KnotLink)。

作用:快速识别 TCP 流中的 KnotLink 帧。接收端读到前两个字节不是 0x4B4B 时,说明对端不是 KnotLink 节点或数据已错位,应立即断开。

Version(协议版本)

当前版本 0x0002

接收端校验规则:与自身支持版本不一致时告警但不拒绝。这是刻意设计——小版本升级不应导致存量节点不可用。若未来引入不兼容变更,会递增主版本号并通过 Magic 扩展机制区分。

Length(消息体长度)

Payload 的字节数,不含 8 字节帧头。最大 16 MB16 × 1024 × 1024)。

发送端:先将消息体序列化为 UTF-8 字节串,计算长度,写入此字段。接收端:读 8 字节帧头 → 取 Length → 继续读取 Length 字节 → 得到一帧。


读写流程

发送端

1. 序列化消息体(KLUDF 键值对 → UTF-8 字节)
2. 写入 Magic: 0x4B4B (2 字节)
3. 写入 Version: 0x0002 (2 字节)
4. 写入 Length: 消息体字节数 (4 字节,大端)
5. 写入 Payload: 消息体字节
6. 通过 TCP socket 发送整帧

接收端

1. 读取 8 字节帧头
2. 校验 Magic 是否为 0x4B4B → 不是则断开
3. 校验 Version 是否匹配 → 不匹配则告警
4. 读取 Length(大端)
5. 读取 Length 字节 → 得到 Payload
6. Payload 反序列化为 KLUDF 键值对 → 交给上层处理
7. 回到第 1 步,读取下一帧

设计考量

为什么不用分隔符。常见的文本协议用 \n\r\n 定界,但 KLUDF 消息体本身是纯文本,可能包含任意字符。用分隔符需要转义,增加解析复杂度。定长帧头 + 长度字段是二进制协议的标准做法,解析只需按偏移读整数,简单且高效。

为什么 16MB 上限。桌面应用间的消息通常是短小的指令或数据片段。16MB 覆盖了绝大多数场景(传一段日志、一个小文件),同时防止恶意或异常节点耗尽内存。

为什么大端序。大端(网络字节序)是 TCP/IP 世界的惯例,跨平台兼容性最好。所有 KnotLink SDK 的实现均使用大端序。


与协议分层的关系

本规范的定位
① 传输层TCP 提供字节流,帧结构在 TCP 之上定界
② 消息体层Payload 使用 KLUDF 格式,帧头不关心 Payload 内容

帧结构是 ① 和 ② 之间的粘合层——TCP 只负责传字节,帧结构告诉接收端"一条消息从哪里开始、到哪里结束"。

协议分层的完整说明见 协议分层