核心概念
在动笔写代码之前,花 5 分钟了解 KnotLink 的两个基本通信模式和接入流程,会让你后面的编码事半功倍。
两种通信模式
KnotLink 提供两种互补的通信模式,覆盖应用间协作的典型场景:
请求-响应模式(Request-Response)
调用方(Querier) 提供方(Responser)
│ │
│ ──── 发送请求 ────▶ │
│ │ 处理请求
│ ◀──── 返回响应 ──── │
│ │
- 特点:一问一答,调用方等待结果
- 类比:调用 API 接口
- 典型场景:查询数据、执行操作、远程控制
- 对应模块:
OpenSocketResponser(提供方)/OpenSocketQuerier(调用方) - 通信拓扑:多对一——多个调用方可以调用同一个提供方
发布-订阅模式(Publish-Subscribe)
发送方(Sender) 守护进程 订阅方 A(Subscriber)
│ │ │
│ ── 发送信号 ──▶ │ ── 广播信号 ──▶ │
│ │ ── 广播信号 ──▶ 订阅方 B
│ │ ── 广播信号 ──▶ 订阅方 C
- 特点:一对多广播,发送方不关心谁收到
- 类比:发广播通知
- 典型场景:事件通知、状态变更、定时广播
- 对应模块:
SignalSender(发送方)/SignalSubscriber(订阅方) - 通信拓扑:一对多——一个发送方,多个订阅方
如何选择?
| 你的需求 | 推荐模式 |
|---|---|
| "帮我做一件事,告诉我结果" | 请求-响应 |
| "告诉所有人,某件事发生了" | 发布-订阅 |
| "两个都需要" | 两者并用 |
许多实际应用两者并用:比如"上课提醒"程序中,教务系统发送信号通知"上课了",语音播报程序订阅信号后播报;同时语音播报程序开放接口让其他程序查询当前播放状态。
接入流程总览
将一个程序接入 KnotLink 协议的完整流程:
确定功能 ──▶ 编写代码 ──▶ 填写功能清单 ──▶ 填写自述清单 ──▶ 发布到节点索引
│ │ │ │ │
│ [coding] [fill-funclist] [packing] [packing]
│ │
└─────────────────────────────────────────────────────────┘
[core-concept](本文)
| 步骤 | 做什么 | 产物 | 对应文档 |
|---|---|---|---|
| ① 确定功能 | 想清楚你的程序要提供什么接口、发送什么信号 | 功能列表 | 本文 |
| ② 编写代码 | 用 SDK 实现通信逻辑(响应请求 / 发送信号) | *.py 源码 | 编写代码 |
| ③ 填写功能清单 | 用 FuncList.json 描述你的接口和信号,供工具链使用 | FuncList.json | 填写功能清单 |
| ④ 填写自述清单 | 用 plugin_manifest.json 声明节点身份,供平台识别 | plugin_manifest.json | 打包与分发 |
| ⑤ 发布 | 提交 plugin_manifest.json + FuncList.json + logo.png 到 KNodeIndex | PR | 打包与分发 |
关键设计原则
功能 ≠ 接口
一个接口可以实现多重功能。例如,同一个 OpenSocketID 可以根据请求参数执行不同的操作:
def handle_request(data: str) -> str:
kv = KLKVMap()
kv.deserialize(data)
action = kv.get("action", "")
if action == "search":
return search_files(kv.get("keyword", ""))
elif action == "delete":
return delete_file(kv.get("path", ""))
else:
return "未知操作"
在 funclist.json 中,你可以用不同的功能条目来描述这些逻辑功能,即使它们共用同一个 OpenSocketID。
消息格式:优先键值对
对于大多数场景,KLUDF 键值对格式(key1=value1;key2=value2)足够且最轻量。只有当数据层级复杂(嵌套对象、数组)时才选用 JSON。
详见 消息体规范
标识符命名规范
KnotLink 支持两种标识符风格,新项目推荐使用新格式:
新格式(推荐)
| 标识符 | 格式 | 示例 | 作用域 |
|---|---|---|---|
appID | 倒置域名 com.<组织>.<应用> | com.example.msgreminder | 全局唯一 |
openSocketID / signalID | 描述性名称 | show、messageReceived | 应用内唯一 |
命名建议:
appID:使用你拥有的域名倒置,或com.<你的GitHub用户名>.<项目名>。一旦发布就不要修改——它是调用方找到你的唯一凭据。openSocketID:用动词或名词描述功能(search、control、getHistory)signalID:用过去式或名词短语描述事件(messageReceived、taskCompleted、fileChanged)
旧格式(兼容)
早期项目使用 0x 开头的 8 位十六进制数字,KnotLink 继续支持这种格式:
| 标识符 | 格式 | 示例 | 作用域 |
|---|---|---|---|
appID | 0x + 8 位十六进制 | 0x00000014 | 全局唯一 |
openSocketID / signalID | 0x + 8 位十六进制 | 0x00000010 | 应用内唯一 |
如果你的项目仍在使用旧格式,无需迁移。新项目建议采用新格式以获得更好的可读性和可维护性。两种格式可以共存于同一个 KnotLink 网络中。
准备开始了?
环境已配置?概念已清楚?进入下一步:编写代码。