重构文件传输的底座:为什么我们放弃了 LocalSend 走向 Rust 自研?
作为 LocalSend、Snapdrop 等优秀开源工具的重度用户,我们最终选择用 Rust 从零自研 xSend。探讨 Dart 垃圾回收、WebRTC 局限性与 Rust 系统级系统编程带来的代差级性能优势。
在决定写下 xSend 的第一行代码之前,我们团队的桌面上安装着市面上几乎所有的开源跨平台文件传输工具:LocalSend、Snapdrop、ShareDrop、Warp 等等。
毫无疑问,像 LocalSend 这样的开源项目极其优秀,它用优雅的用户界面拯救了无数在 iOS、Windows 和 Android 之间饱受文件传输折磨的用户。Snapdrop 则用纯浏览器的体验定义了什么是“即用即走”。
但当我们面临超大工程文件迁移、跨复杂 NAT 网络直连、以及对内存和 CPU 有严苛要求的后台常驻场景时,我们发现这些基于上层应用框架构建的传输工具,逐渐暴露出底层的物理极限。
这就是我们决定用 Rust 从零重构底层网络栈,打造 xSend 的初衷。我们想要跨越的,是下面这三条无法通过简单修补来跨越的技术鸿沟。
1. 跨越垃圾回收 (GC) 的鸿沟:Dart vs Rust
LocalSend 是使用 Flutter/Dart 构建的。Flutter 是一个极其优秀的移动端跨平台 UI 框架,但当涉及到网络 I/O 密集型操作时,Dart 语言自带的垃圾回收器 (Garbage Collector, GC) 成了隐形的性能吞吐量杀手。
在进行数 GB 甚至上百 GB 的文件传输时,程序需要在内存中无休止地申请和释放缓冲区(Buffer)。
- GC 的代价:Dart 在高强度对象创建和销毁时,GC 可能会触发短暂的 Stop-the-World,导致网络流出现微小的抖动。同时,为了维持高吞吐,虚拟机往往需要吃掉大量的内存。
- Rust 的零成本抽象:xSend 的核心传输引擎完全用 Rust 编写。Rust 独特的所有权与生命周期机制(Ownership & Lifetimes),让我们可以在编译期就精确预测内存的分配与释放,彻底消灭了运行时的垃圾回收。
- 结果:xSend 作为后台守护进程常驻在系统中时,内存占用通常只有几兆字节。而在极限传输时,它能以稳定的、毫无波动的曲线榨满千兆/万兆网卡,即使在老旧配置的软路由或低端 Android 设备上,资源占用依然微乎其微。
2. 打破沙盒的桎梏:从纯 WebRTC 到系统级网络栈
另一种极其流行的方案是 Snapdrop 或 ShareDrop,它们完全依赖浏览器底层的 WebRTC。
如我们在前一篇文章中所述,WebRTC 是杰出的。xSend 的网页端也原生支持纯浏览器传输。但只做一个网页版的工具,注定无法突破性能的终极天花板。
- 浏览器受到严苛的安全沙盒限制,所有的磁盘读写(File API)和网络数据包发送,都要经过层层复制。
- 更痛苦的是,纯浏览器工具无法在后台运行。只要手机熄屏,或者你切换到了其它多任务窗口,传输就会被系统强行挂起甚至杀死。
xSend 的破局之道是“全端 Native 核心化”。我们的 Rust 核心被编译为底层动态链接库运行在桌面和移动端,它拥有最底层的系统权限,直接操作 TCP Socket 和现代自带加密的 QUIC 协议。这带来了真正的后台防崩溃续传和超越浏览器极限 3-5 倍的局域网吞吐能力。
3. 终结“非同一子网”的尴尬:Auto-Route 智能路由
如果你用过大多数开源 LAN 传输工具,一定遇到过这个经典痛点:“我们明明在同一个公司,为什么搜索不到对方?”
原因很简单:大型公司的 Wi-Fi 通常划分了多个 VLAN,传统的 mDNS/UDP 局域网广播搜寻包会被路由器直接丢弃。对于 LocalSend 来说,如果你不知道对方的确切 IP,传输往往就此中断。
xSend 在架构设计的第一天就引入了 自动路由分层网络 (Auto-Route):
- 第一层 (LAN Native):在同一子网内,照常通过 UDP 发现,建立纯 TCP 高速通道。
- 第二层 (WAN P2P / 穿透):如果不在同一子网,只要输入 6 位提取码,系统会自动通过我们的 Cloudflare Worker 信令节点,尝试广域网 UDP 打洞,建立 QUIC 隧道直连。
- 第三层 (TURN Relay 兜底):哪怕双方处于全封闭的企业对称 NAT 防火墙下,流量也会无缝切换至加密的端到端中继通道。
传输不会中止。用户不需要懂什么是 IP 地址,不需要懂什么是网段,只要 6 位码,系统自己会去试探最优的物理路径。
结语:为什么是 Rust?
我们并不是在否认 Flutter 或 Node.js 的价值(事实上,xSend 的桌面壳依然采用了 Tauri,前端用了 React,因为它们在画界面时无与伦比)。
但在系统的神经中枢与心血管系统上,我们需要一种运行速度媲美 C/C++,但绝不漏水、绝不越权的现代工程语言。Rust 强悍的并发模型保证了我们的异步网络栈(通过 Tokio)坚如磐石,其强大的密码学库让 ChaCha20-Poly1305 加密像呼吸一样自然。
所以,这就是 xSend。不是对 LocalSend 的简单借鉴,而是在深刻体验了所有同类工具后,一次彻头彻尾的、面向极限性能与复杂网络的底层重构。