LocalSend:基于 Rust 与 Flutter 的局域网文件共享方案——协议原理、网络配置与源码构建全解
【免费下载链接】localsendAn open-source cross-platform alternative to AirDrop项目地址: https://gitcode.com/GitHub_Trending/lo/localsend
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 appbundleiOS
flutter build ipamacOS
flutter build macosWindows
# 传统 EXE flutter build windows # 本地 MSIX 包 flutter pub run msix:create # 应用商店就绪的 MSIX flutter pub run msix:create --storeLinux
# 传统构建 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 传输实现了无云、可控、跨平台的局域网文件共享。以上每一点都能在当前仓库的文档与源码中找到对应证据。
【免费下载链接】localsendAn open-source cross-platform alternative to AirDrop项目地址: https://gitcode.com/GitHub_Trending/lo/localsend
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考