LocalSend:基于 Rust 与 Flutter 的局域网文件共享方案——协议原理、网络配置与源码构建全解
LocalSend 是一款开源的跨平台“隔空投送”替代应用,允许设备在本地网络上通过 REST API 与 HTTPS 加密安全地互传文件和消息,全程无需互联网连接或第三方服务器。本文以仓库根目录的 README.md 为核心骨架,结合 packages/core 的 Rust 源码、Cargo feature 配置与构建脚本,深入讲解它的通信原理、端口与防火墙配置、各平台兼容性、从源码编译到产物构建的完整流程,以及常见问题排查方法。读完本文,你将能够独立部署 LocalSend、正确配置网络放行规则,并理解其“证书指纹识别设备”的安全设计。
项目定位:为什么需要 LocalSend
从 README.md 的 About 章节可以确认 LocalSend 的核心定位:
- 跨平台:覆盖 Android、iOS、macOS、Windows、Linux 与 Fire OS;
- 安全通信:基于 REST API + HTTPS 加密,TLS/SSL 证书在每台设备上动态生成(on the fly);
- 无外网依赖:不依赖任何外部服务器或互联网连接,完全在局域网内点对点工作。
这一设计使它区别于依赖云端中转的常规传输方式:设备之间直接发现、直接握手、直接传输,速度与可靠性只取决于局域网本身。
整体架构与依赖层级
仓库根目录下的 依赖层级图(由 dependency-hierarchy.d2 用 D2 语言生成)展示了项目的分层结构,这是理解整个代码库的地图:
从 dependency-hierarchy.d2 的源文件看,架构分为两层:
| 层 | 模块 | 语言 | 职责 |
|---|---|---|---|
| 消费者层 | app/ | Dart/Flutter | 跨平台图形应用 |
| 消费者层 | cli/ | Rust | 命令行界面 |
| 消费者层 | server/ | Rust | WebRTC 信令服务器 |
| 适配层 | packages/localsend_isolates/ | Dart + Rust | 后台线程与 Rust 绑定(Flutter-Rust-Bridge) |
| 核心层 | packages/core/ | Rust | 实现 LocalSend 协议的基础库 |
关键调用关系是:app 不直接依赖 core,而是经由 localsend_isolates(Dart 层通过隔离线程 + Rust 绑定)间接使用核心协议库;cli 与 server 则直接依赖 core。这种设计让图形应用的重活(协议、加密、传输)都在 Rust 隔离线程中执行,避免阻塞 Dart 的 UI 事件循环。
根目录的 pubspec.yaml 表明这是一个 Dart workspace,聚合了 app、packages/localsend_isolates 与 packages/typed_isolates 三个成员包。
工作原理:REST API + 动态自签名证书
README.md 的 “How It Works” 指出:LocalSend 使用一套安全通信协议,设备间通过 REST API 交互,所有数据经 HTTPS 传输,且 TLS/SSL 证书在每台设备上即时生成。
在 packages/core/src/crypto/cert.rs 中可以印证并深化这一机制:
- 设备身份是一个 RSA-2048 密钥对 + 自签名证书(
generate_self_signed()),私钥以 PKCS#8 PEM 编码保存,证书CN=LocalSend User且不含 SAN; - 由于不依赖 CA,对端设备完全通过证书的 SHA-256 指纹(DER 编码、大写十六进制)来识别和配对彼此,证书名字不携带任何身份信息;
- 证书有效期取 rcgen 默认值(1975–4096 年),实际上永不过期,无需因时间轮换;
- 校验逻辑(
verify_cert_from_cert)会检查签名、时间有效性与公钥匹配。
换言之,LocalSend 的“信任”不是 CA 体系,而是设备指纹配对:首次连接时用户确认对方指纹,之后凭指纹建立信任——这与 AirDrop 式的“确认设备”体验一致。
协议核心库的功能模块划分
packages/core/Cargo.toml 通过 Cargo feature 将协议拆成可裁剪的模块:
| Feature | 依赖的关键 crate | 职责 |
|---|---|---|
crypto |
rsa、rcgen、ed25519-dalek、sha2 |
证书/密钥生成、哈希 |
multicast |
if-addrs、socket2 |
组播网络广播,用于设备发现 |
http |
hyper、reqwest、rustls、tokio-rustls |
REST API 服务与客户端(HTTPS 传输) |
discovery |
依赖 http + multicast |
组合能力:发现对端并建立通信 |
webrtc |
webrtc、flate2 |
WebRTC 通道(可用于 NAT 后/组播受限场景) |
full |
以上全部 | 完整协议栈 |
默认 feature 为空(default = []),各消费方按需开启——例如 CLI 只取所需子集,App 走 full。从源码结构看,discovery 对 http 与 multicast 的依赖关系(Cargo.toml)正体现了“先组播发现、再 HTTPS 传输”的协议流程;packages/core/src/discovery/store.rs 中默认端口常量即为 53317,与 README 的防火墙配置表一致。
下载与平台兼容性
README.md 的 Download 章节提供了各平台分发渠道的完整清单,并给出明确的兼容性下限:
| 平台 | 最低版本 | 备注 |
|---|---|---|
| Android | 5.0 | — |
| iOS | 12.0 | — |
| macOS | 11 Big Sur | 更老系统可尝试 OpenCore Legacy Patcher 2.0.2 |
| Windows | 10 | 最后一个支持 Windows 7 的版本为 v1.15.4 |
| Linux | N.A. | GNOME 需 xdg-desktop-portal 与 xdg-desktop-portal-gtk;KDE 需 xdg-desktop-portal-kDE 变体 |
分发渠道按平台组织(README 中为链接表格,此处仅列名称):
- Windows:Winget、Scoop、Chocolatey、EXE 安装包、便携式 ZIP;
- macOS:App Store、Homebrew、DMG 安装包;
- Linux:Flathub、Nixpkgs、Snap、AUR、TAR/DEB/AppImage;
- Android:Play Store、F-Droid、APK 直装;
- iOS:App Store;Fire OS:Amazon 商店。
README 同时强调两点工程事实:
- 由于应用没有自动更新,推荐通过应用商店或包管理器安装;
- Windows 二进制文件经过签名,签名策略见 CODE_SIGNING.md。
网络配置:端口、防火墙与路由器
README.md 的 Setup 章节给出了部署 LocalSend 最常被忽略的网络要求。大多数情况下开箱即用,但发送/接收失败时通常出在防火墙或路由器上:
防火墙规则
| 流量方向 | 协议 | 端口 | 动作 |
|---|---|---|---|
| 入站 (Incoming) | TCP, UDP | 53317 | 允许 |
| 出站 (Outgoing) | TCP, UDP | 任意 | 允许 |
端口 53317 在仓库中多处可验证:CLI 配置默认值(cli/src/storage/config.rs 中 DEFAULT_PORT: u16 = 53317)、CLI 帮助文本(cli/src/main.rs “[default: config.toml, else 53317]”)、发现模块测试数据(packages/core/src/discovery/store.rs)。
路由器 AP 隔离
必须确保路由器关闭 AP 隔离(AP Isolation)。该选项默认通常关闭,但部分路由器(尤其访客网络)会开启它,一旦开启,接入同一 Wi-Fi 的设备之间将禁止互通,LocalSend 自然无法发现彼此。
便携式模式(Portable Mode)
v1.13.0 引入:在可执行文件同级目录创建一个 settings.json(内容可为空),应用即改用该文件存储设置,而非系统默认位置。适合放在 U 盘里跨机器携带配置使用。
隐藏启动(Start hidden)
v1.15.0 更新:使用 --hidden 标志启动(例如 localsend_app.exe --hidden),应用将仅驻留系统托盘而不弹出窗口。v1.14.0 及更早版本的行为不同:当设置了 autostart 标志且隐藏选项开启时才会隐藏启动——升级后需注意这一变化。
故障排查手册
README.md 的 Troubleshooting 表格按“发送端平台 × 接收端平台”维度归纳了五类典型问题,是排障的第一入口:
| 问题 | 发送端 | 接收端 | 解决方案 |
|---|---|---|---|
| 设备不可见 | 任意 | 任意 | 关闭路由器 AP 隔离;开启后设备间连接被禁止 |
| 设备不可见 | 任意 | Windows | 将网络类型设为“专用 (private)”;Windows 对“公用”网络的限制更严格 |
| 设备不可见 | macOS、iOS | 任意 | 在系统设置的“隐私”中切换“本地网络”权限 |
| 速度过慢 | 任意 | 任意 | 改用 5 GHz Wi-Fi;双端同时关闭加密 |
| 速度过慢 | 任意 | Android | 已知问题(与 SAF 流式文件访问的实现相关) |
仓库还提供了一个专门的故障排查界面入口:app/lib/pages/troubleshoot_page.dart,说明这些问题在应用内也有对应的诊断引导。
从源码编译:环境与步骤
README.md 的 Getting Started 给出了六步流程,结合仓库实际文件补齐版本约束:
- 安装 Flutter(直接安装或借助 fvm 管理);所需版本见 .fvmrc。从 app/pubspec.yaml 看,要求 Flutter ^3.41.0 / Dart ^3.11.0;
- 安装 Rust。根目录 rust-toolchain.toml 锁定 Rust 1.97.1 并附带 clippy 组件;跨平台编译目标(Android aarch64/armv7/x86_64、macOS aarch64/x86_64)在 packages/localsend_isolates/rust-toolchain.toml 中声明;
- 克隆 LocalSend 仓库;
cd app进入应用目录;flutter pub get下载依赖;flutter run启动应用。
README 附有一条重要 NOTE:LocalSend 当前要求一个特定版本的 Flutter,系统级 Flutter 版本不匹配会造成构建问题;项目用 fvm 统一管理版本,安装后请用 fvm flutter 替代 flutter 命令执行。仓库采用 Dart workspace(pubspec.yaml),因此依赖解析覆盖整个工作区。
各平台产物构建命令
README.md 的 Building 章节声明:以下命令面向维护者,且必须从 app 目录执行:
Android
# 传统 APK
flutter build apk
# Google Play 用的 AppBundle
flutter build appbundle
iOS
flutter build ipa
macOS
flutter build macos
Windows
# 传统 EXE
flutter build windows
# 本地 MSIX 包
flutter pub run msix:create
# 应用商店就绪的 MSIX
flutter pub run msix:create --store
Linux
# 传统构建
flutter build linux
# AppImage
appimage-builder --recipe AppImageBuilder.yml
# Snap:见上游 snap 仓库的说明
仓库的 support/scripts/ 目录提供了对应的 CI 级构建脚本,可作为上述命令的自动化参考实现:如 compile_android_apk.sh、compile_mac_dmg.sh、compile_windows_exe.ps1、compile_linux_appimage.sh 等。此外 app/linux/packaging/ 下有 deb/rpm 的 make 配置,app/macosos/ 与 app/ios/ 则包含原生壳工程(含 ShareExtension、托盘/状态栏集成等平台特定能力)。
多语言支持与贡献路径
README.md 的 Contributing 章节说明了两条主要贡献路径:
- 翻译:使用 Weblate 平台协作,或 fork 后手工提交。翻译文件位于 app/assets/i18n/ 目录,需要编辑
strings_<locale>.i18n.json或_missing_translations_<locale>.json。该目录当前已覆盖中文(zh-CN.json、zh-TW.json、zh-HK.json)、日文、韩文、法文等 70+ 语言。README 特别提醒:带@前缀的字段仅作上下文说明,不参与翻译; - Bug 修复与改进:Bug 修复直接提 PR 并附清晰说明;改进类建议先开 issue 讨论必要性。更完整的规范见 CONTRIBUTING.md。
本地生成的字符串 Dart 代码(如 app/lib/gen/strings_zh_CN.g.dart)由 app/lib/util/i18n.dart 等运行时模块消费,说明翻译文件会经代码生成环节注入应用。
延伸阅读:仓库内可继续深入的位置
| 主题 | 路径 |
|---|---|
| 协议核心库(发现/HTTP/加密/WebRTC) | packages/core/src/ |
| 自签名证书实现 | packages/core/src/crypto/cert.rs |
| 协议集成测试(v2 服务、TLS pinning、Web 下载等) | packages/core/tests/ |
| 隔离线程与 Rust 绑定层 | packages/localsend_isolates/ |
| 命令行客户端 | cli/src/ |
| WebRTC 信令服务器 | server/src/ |
| Windows 代码签名策略 | CODE_SIGNING.md |
| 版本变更记录 | CHANGELOG.md |
| 其他语言 README | support/readme/README_ZH.md 等 |
综合来看,LocalSend 的工程价值在于:用一套 Rust 核心协议库(可 feature 裁剪)同时支撑 Flutter 图形应用、CLI 与信令服务器三种形态;用“动态自签名证书 + 指纹配对”替代 CA 体系完成设备间信任;并靠 53317 端口的组播发现 + HTTPS REST 传输实现了无云、可控、跨平台的局域网文件共享。以上每一点都能在当前仓库的文档与源码中找到对应证据。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00