LocalSend 技术指南:基于 REST + HTTPS 的跨平台局域网文件传输实现与源码编译实战
LocalSend 是一款免费开源的跨平台 AirDrop 替代品,它不依赖互联网和任何第三方服务器,仅凭 REST API 与 HTTPS 加密就能在局域网内安全地互传文件与消息。本篇以官方日文 README(support/readme/README_JA.md)的骨架为主线,结合仓库中的 Rust 核心源码(packages/core)与 Flutter 应用配置(app/),完整讲清 LocalSend 的通信原理、各平台分发渠道与兼容性边界、从源码编译的完整步骤,以及常见问题的排查方法。
一、项目概览:不经过互联网的点对点共享
LocalSend 的定位非常明确:免费、开源、跨平台、无需互联网连接。它允许本地网络上的邻近设备之间安全地共享文件和消息。
与依赖外部服务器的消息应用不同,LocalSend 直接采用 REST API 与 HTTPS 加密完成设备间通信,是本地文件传输场景下快速且可靠的解决方案。当前仓库的应用版本为 1.18.2+64(见 app/pubspec.yaml),整个工程是一个 Flutter 与 Rust 混合的项目:
- app/:Flutter 应用主体(Android/iOS/macOS/Windows/Linux/Web);
- packages/core/:Rust 实现的核心库,包含加密、发现、HTTP 服务器/客户端、UDP 组播等协议层代码;
- cli/:基于 Rust 核心的命令行收发工具;
- server/:可 Docker 部署的独立服务端(见 server/README.md)。
二、工作原理:动态 TLS 证书 + 局域网发现
官方 README 对"仕組み(How it works)"的描述是:LocalSend 使用一套安全的通信协议让设备通过 REST API 互相通信,所有数据都通过 HTTPS 传输,TLS/SSL 证书在每个设备上动态生成,以此保证最高级别的通信安全。协议细节由独立的 localsend/protocol 仓库维护,而当前仓库中 packages/core 的实现可以精确印证这句话。
2.1 设备身份:每台设备自签一张 RSA-2048 证书
从源码结构看,设备身份的生成与校验集中在 packages/core/src/crypto/cert.rs。generate_self_signed() 函数会:
- 生成 RSA-2048 非对称密钥对(与 Flutter 应用早期在 Dart 中生成的证书规格保持一致);
- 自签一张证书,
CN=LocalSend User、不带 SAN——因为对端完全靠证书指纹互相识别,证书名不承载任何身份信息; - 序列号取自公钥哈希;有效期采用 rcgen 默认值(1975~4096),实际上证书不会过期,也就不需要按时间轮换;
- 计算证书 DER 字节的 SHA-256 指纹,编码为大写十六进制(
fingerprint_from_cert_der),这就是 LocalSend 界面上用于配对确认的设备指纹。
verify_cert_from_pem() 则负责校验对端证书:依次检查时间有效性、公钥是否匹配(不匹配单独报错 Public key mismatch,便于单元测试)、以及自签名签名本身(cert.verify_signature)。该文件内的单元测试覆盖了签名被篡改、公钥不匹配、证书过期三类失败场景,并用固定向量验证了指纹算法与 Dart 侧完全一致。
2.2 设备发现:UDP 组播广播 + HTTP 注册
"发现邻近设备"的实现分两层,均在 packages/core/src/multicast/mod.rs 与 packages/core/src/discovery/mod.rs:
- 组播广播:设备周期性地向组播组
224.0.0.167(UDP 端口 53317,与 HTTP 服务默认端口相同)发送MulticastMessageV2宣告。之所以选择224.0.0.0/24网段,源码注释说明:在部分 Android 设备上这是唯一能收到 UDP 组播消息的 IP 范围。LocalSend 还扩展了 IPv6 组播(ff12::fd3a:e420,链路本地作用域的瞬态组),与 IPv4 并行宣告。为应对"单个数据报易丢失、刚加入网络的设备尚未就绪"的问题,每次宣告按 100ms / 500s / 2000ms 的间隔连发 3 次(ANNOUNCE_DELAYS)。 - HTTP 注册:组播只是"敲门",真正的握手是响应方向宣告者发起的 HTTP register 请求(携带客户端 TLS 证书——HTTPS 模式下客户端证书是强制的)。
DiscoveryConfig中定义了每次注册请求的默认超时DEFAULT_DISCOVERY_TIMEOUT = 500ms(局域网对端要么秒回、要么不回),子网扫描的并发度为 50(SCAN_CONCURRENCY)。
这套"组播发现 + 每设备自签证书的 HTTPS 注册"的组合,正是 README 中"所有数据 HTTPS 加密、证书动态生成"这一句话的完整落地。
三、下载与分发渠道
由于 LocalSend 没有内置自动更新功能,官方建议从应用商店或包管理器获取应用,以便持续获得更新。按平台划分的主要渠道如下(仓库内 CONTRIBUTING.md 的 Distribution 小节列出了各 Git 分发渠道的仓库与维护者):
| 平台 | 渠道 |
|---|---|
| Windows | Microsoft Store、Winget、Scoop、Chocolatey、EXE 安装包、Portable ZIP |
| macOS | App Store、Homebrew、DMG 安装包 |
| Linux | Flathub、Nixpkgs、Snap、AUR、DEB / TAR / AppImage |
| Android | Google Play、F-Droid、APK |
| iOS | App Store |
| Fire OS | Amazon Appstore |
3.1 各平台最低版本要求
官方 README 给出的兼容性矩阵如下,是选择安装方式前的重要参考:
| 平台 | 最低版本 | 备注 |
|---|---|---|
| Android | 5.0 | - |
| iOS | 12.0 | - |
| macOS | 11 Big Sur | 旧机型可使用 OpenCore Legacy Patcher 2.0.2 支持(官方 issue #1005 有讨论) |
| Windows | 10 | 最后一个支持 Windows 7 的版本是 v1.15.4,未来可能为 Win7 做新版本反移植 |
| Linux | N.A. | 依赖:GNOME 需 xdg-desktop-portal 与 xdg-desktop-portal-gtk;KDE 需 xdg-desktop-portal 与 xdg-desktop-portal-kde |
其中 Linux 的依赖项值得注意:LocalSend 依赖 xdg-desktop-portal 提供的文件选择/打开能力,GNOME 与 KDE 桌面各自需要对应的 portal 后端,缺失时文件选取功能会不可用。
四、开始使用:从源码编译
官方文档给出的编译步骤如下(对应当前仓库结构可直接执行):
- 安装 Flutter(官方渠道或 fvm,本仓库要求 3.41.9,见 .fvmrc);
- 克隆 LocalSend 仓库;
cd app进入应用目录;flutter pub get下载依赖;flutter run启动应用。
几个从仓库配置可以确认的关键约束:
- .fvmrc 固定为
"flutter": "3.41.9",而 app/pubspec.yaml 声明flutter: ^3.41.0、Dartsdk: ^3.11.0。README 特别提醒:LocalSend 依赖较旧的 Flutter 版本,构建问题很可能源于项目要求版本与系统全局安装版本不一致。因此官方推荐用 fvm 管理项目级 Flutter 版本——安装 fvm 后,把命令行中的flutter替换为fvm flutter执行即可。 - 顶层 pubspec.yaml 将
app、packages/localsend_isolates、packages/typed_isolates组织为一个 Flutter workspace;packages/localsend_isolates 通过 Rust 工具链(cargo 构建,跨平台由 cargokit 封装)把packages/core的能力桥接进 Flutter isolate,这也是flutter run时 Rust 侧会一并编译的原因。 - 顶层还存在 rust-toolchain.toml,用于统一 Rust 工具链版本,避免不同开发机的 Rust 版本差异。
五、参与贡献
LocalSend 欢迎社区贡献,官方 README 列出了两条主要路径:
5.1 翻译
推荐方式是通过 Weblate 平台(hosted.weblate.org 上的 LocalSend/app 项目)集中管理翻译;也可以 fork 本仓库手动添加翻译文件。
翻译资源位于 app/assets/i18n,目录中同时包含两类文件:
strings_<locale>.json(如zh-CN.json、ja.json):各语言的实际译文;_missing_translations_<locale>.json:由构建流程生成的"缺失翻译"清单,用于跟踪每种语言尚未覆盖的条目。
应用侧使用 slang 代码生成工具(见 app/pubspec.yaml 中的 slang / slang_flutter 依赖及 app/gen/strings_*.g.dart)从这些 JSON 生成 Dart 本地化代码。
官方特别注明:以
@修饰的字段不是待翻译项,它们只是供翻译者理解上下文的信息性文本,不会被应用使用。
5.2 修 Bug 与改进
- Bug 修复:创建 Pull Request,并在其中清晰说明问题描述与修复方式;
- 功能改进:先在 issue 区发起讨论,说明改进动机后再动手。
更完整的规范(含安全问题的报告方式:安全问题请勿公开提 issue,应邮件 support@localsend.org)见 CONTRIBUTING.md。
六、故障排查
官方 README 附有一张排查矩阵,覆盖"找不到设备"和"速度慢"两大类问题,这里完整保留:
| 问题 | 平台(发送方) | 平台(接收方) | 解决方法 |
|---|---|---|---|
| 设备不显示 | 所有 | 所有 | 在路由器上关闭 AP-Isolation(AP 隔离)。若开启,设备间的直接通信会被路由器禁止——这是与组播/广播发现机制直接冲突的典型配置 |
| 设备不显示 | 所有 | Windows | 把网络类型设置为"专用(私有)"网络;若被设为"公用",Windows 的网络策略会更加严格 |
| 设备不显示 | macOS / iOS | 所有 | 在系统"隐私"设置下切换"本地网络"权限 |
| 速度太慢 | 所有 | 所有 | 使用 5 GHz 频段;并在两台设备上都关闭加密(牺牲安全性换取速度) |
| 速度太慢 | 所有 | Android | 已知问题(与 Flutter 侧 SAF 流式读取实现有关,属上游依赖的已知限制) |
结合第二节的原理可以这样理解这张表:设备发现依赖组播与 500ms 超时的快速注册探测(packages/core/src/discovery/mod.rs),AP 隔离、公用网络策略、以及操作系统对本地网络权限的拦截,都会直接切断这一链路;而传输速度则取决于实际选用的 Wi-Fi 频段与是否启用 TLS 加密。
七、小结
LocalSend 用一条很"朴素"的技术路线解决了局域网共享的核心难题:每台设备自签 RSA-2048 证书并以 SHA-256 大写十六进制指纹互认(packages/core/src/crypto/cert.rs),UDP 组播(224.0.0.167:53317)广播宣告 + 短超时 HTTP 注册完成发现(packages/core/src/multicast/mod.rs),此后所有数据走设备间动态建立的 HTTPS 通道,全程不出局域网。对于想在同类场景下设计"无服务端、强本地性"的通信方案,这套"自签证书 + 指纹识别 + 组播发现 + 短超时注册"的组合值得直接参考;而本文第二至四节给出的源码路径与 support/readme/README_JA.md 的原始步骤,足以支撑从原理理解到本地编译运行的完整链路。
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