多端形态:CLI/IPC/Web/桌面/Android

专栏:VNT 2.0 组网源码 · 第 10 / 11 篇
VNT架构多平台

:::info 学习目标 完成本篇后你能够:解释”核心与载体分离”的架构收益;对比五种载体的控制通道取舍;说出 Android 端 startTun(fd) 的协作模型。 前置:第 3 篇完成。预计时长:60 分钟。 :::

:::note 本章术语速查(新手建议先读)

  • IPC(进程间通信):同一台电脑上两个进程交换数据(管道/socket/共享内存等)。
  • axum:Rust 最流行的 Web 框架之一。
  • oneshot:一次性通道——发一个值,接收方收到即完成。
  • RustEmbed:编译时把静态文件(如前端产物)嵌进二进制。
  • FFI:两种语言互相调用的边界(如 Java 调 Rust)。
  • panic:Rust 的“程序崩溃”——跨语言边界时必须拦住。 :::

vnt 2.0 的架构决定:所有组网逻辑收进 vnt-core 一个 crate,载体只做壳。同一个人机能力,五种形态各按场景取用:

图表(vnt-multi-platform.md)

vnt2_cli / vnt2_ctrl:TCP IPC 而非管道

vnt2_cli 是干活的常驻进程;查询交给独立的 vnt2_ctrl(整个文件 43 行,4 个子命令 Info/Ips/Clients/Route 映射为 protobuf IpcCmd)。两者的通道是 loopback TCP(默认 11233)+ protobuf + 帧编解码——不是 unix socket。

两个工程细节值得学:PORT 文件的锚定——写进”可执行文件同目录”而非 CWD(否则换个目录启动就读不到了);PORT 文件只由绑定到默认端口的实例写——第二个实例(显式指定端口或冲突退避到随机端口)都不写,防止多实例互相覆盖导致查询到错误的进程。客户端发现顺序:--port 参数 > PORT 文件 > 默认 11233,连接 3 秒超时、响应 5 秒超时——一个只读查询工具的健壮性也毫不将就。

vnt2_web:axum 管理面

vnt2_web 面向无桌面环境(服务器/NAS):启动时生成 48 字符随机 token 打进访问 URL,浏览器里管理多个组网实例(每个实例独立的配置 TOML、状态机 Stopped/Starting/Running、冲突检测)。13 个 REST API 走 Bearer 鉴权,Vue3 前端经 RustEmbed 编进二进制。token 消费后 history.replaceState 从 URL 抹除——细节见功力。

vnt-desktop:进程内直调,不开端口

桌面端(Tauri 2)与 Web 共用同一套 Vue 应用(vnt-web/ui 通过 vite alias 共享),差异只在桥接层:桌面前端的 __VNT_IPC_REQUEST__ 不走 HTTP,而是 invoke Tauri 命令 api_request → 进程内 oneshot 直调 axum Router——

// vnt-desktop/src-tauri/src/lib.rs:136-151(节选)
#[tauri::command]
async fn api_request(..., path: String, ...) -> Result<serde_json::Value, String> {
    if !path.starts_with("/api/") {
        return Err("只允许调用 VNT API".to_string());
    }
    state.service.request(&method, &path, body).await...
}

同一套 API、零网络端口、零 token 管理(进程内没有别人)。需要浏览器访问时按需开启(web_access.toml,token 至少 16 字符)——桌面端把”要不要暴露网络服务”变成一个显式的用户决定。这是三种控制通道里安全模型最干净的一种。

vnt-jni:Android 的 fd 移交

Android 不能自己建 TUN,必须走系统 VpnService。JNI 层(cdylib,jni 0.21)的协作模型:

图表(vnt-multi-platform.md)

所有 JNI 入口用宏捕获 panic(防跨 FFI 展开)、实例用 i64 句柄表管理、配置与查询全走 JSON 字符串——FFI 边界尽量窄的典型实践。

常见踩坑

  1. vnt2_ctrl 连不上——cli 是否启动、PORT 文件位置(exe 旁)、ctrl_port=0 是否显式禁用;
  2. Web token 丢了——看启动日志的 Web access URL,或 --token 固定;
  3. Android 上 establish 返回 -1——VPN 权限未授予或重复 establish。

随堂练习(带验收标准)

  1. 同时跑 vnt2_cli 与 vnt2_ctrl,用 ss -tnp 确认 11233 的 IPC 连接;
  2. 起一个 vnt2_web,用两个浏览器标签管理两个组网实例。验收:实例间状态互不干扰;
  3. 进阶:对照 vnt-web/ui 与 vnt-desktop/src/main.js,画出”同一 Vue 应用如何适配两种宿主”的桥接图。

← 返回文章列表