12 个版本 (破坏性更新)
0.10.2 | 2024 年 7 月 21 日 |
---|---|
0.9.0 | 2024 年 7 月 13 日 |
#264 在 网络编程
每月 208 次下载
180KB
4K SLoC
快速文件传输
qft
目的
注意!这是一个正在进行中的项目,并不适合生产环境
在本地网络中尽可能快速、安全、轻松地传输文件。
此说明文档也以书籍的形式提供。
qft
优化了嵌入式系统在本地网络中定期传输大文件的场景,例如持续集成管道中固件(例如 Rauc)传输,这些工具包括 rsync
、scp
或 netcat
(注意:不要以此方式升级 Rauc,而应使用 delta 或 自适应升级)。
为了实现这一点,qft
作为服务器/客户端通过 TCP 传输数据。它与 netcat
传输文件的方式非常相似,但 qft
仅关注文件传输,并附带各种自定义选项,如 压缩/解压缩、内存映射、预分配选项等。TCP 被选为可靠的数据传输,且没有添加身份验证或加密以减少开销,还支持通过 mDNS 定位远程目标。
如果您担心中间人攻击,可以在继续之前简单地检查接收端的数据。应该没有额外的安全顾虑(如果您不同意,请创建一个问题,突出显示您的担忧)。
特性
- 通过指定 IP 地址或主机名通过 TCP 发送文件(包括 mDNS/DNS-SD)
- 评估输入数据的 支持的压缩格式
- 发现、解析和/或注册 mDNS/DNS-SD 服务
- 类似SCP的传输
qft ssh FILES... <user>@<host>:<path>
。认证通过SSH进行,但传输是裸骨TCP。 - 为
bash
、elvish
、fish
、powershell
和zsh
提供shell补全。
默认启用所有功能,要禁用功能请参阅安装部分。
用法
$ qft -h
Usage: qft [OPTIONS] [COMMAND]
Commands:
listen Run in Listen (server) mode
send Run in Send (client) mode
mdns Use mDNS utilities
evaluate-compression Evaluate which compression works best for file content
get-free-port Get a free port from the host OS. Optionally specify on which IP or a port range to scan for a free port
ssh SCP-like - Send to a target that might not have qft actively listening, authenticating over SSH and transferring over TCP
help Print this message or the help of the given subcommand(s)
Options:
-v, --verbose... Pass many times for more log output
-q, --quiet Silence all log output, this will lead to better performance [env: QFT_QUIET=]
--color=<WHEN> [default: auto] [possible values: auto, always, never]
--completions <SHELL> Generate completion scripts for the specified shell. Note: The completion script is printed to stdout [possible values: bash, elvish, fish, powershell, zsh]
-h, --help Print help (see more with '--help')
-V, --version Print version
示例
文件传输
在CI脚本中使用基于密钥的SSH认证时,它看起来非常类似于SCP。
两个主机都需要安装qft!
主机 #1
qft ssh file.data [email protected]:/tmp/
无SSH认证的CI脚本
类似树莓派这样的设备可以编排嵌入式系统的测试,并且可能使用这样的脚本传输固件升级包。
#!/usr/bin/env bash
set -eu
REMOTE_HOSTNAME="foo.local."
FIRMWARE="fw.raucb"
qft ssh ${FIRMWARE} root@${REMOTE_HOSTNAME}:/
ssh root@${REMOTE_HOSTNAME} -t "rauc install /${FIRMWARE}"
...
还可以使用 qft mdns register
临时注册服务,并且可以并行运行 qft listen
,然后通过从远程主机指向已注册的主机名来向监听进程发送。
评估压缩
Evaluate which compression works best for file content
Usage: qft evaluate-compression [OPTIONS] --input-file <INPUT_FILE>
Options:
Evaluate which compression works best for file content
Usage: qft evaluate-compression [OPTIONS] --input-file <INPUT_FILE>
Options:
-i, --input-file <INPUT_FILE>
--omit [<OMIT>...] List of compression formats to omit from evaluation [possible values: bzip2, gzip, lz4, xz]
--omit-levels [<OMIT_LEVELS>...] List of compression levels to omit from evaluation
-j, --threads <jobs> The number of threads to use to evaluate compression (1 = sequential), the default is calculated from the available CPUs on the host [default: 14]
-v, --verbose... Pass many times for more log output
-q, --quiet Silence all log output, this will lead to better performance [env: QFT_QUIET=]
--color=<WHEN> [default: auto] [possible values: auto, always, never]
-h, --help Print help (see more with '--help') Print help (see more with '--help')
演示

输出示例
评估 Cargo.lock
的压缩。省略 gzip
和大多数压缩级别以使此示例简短。
qft evaluate-compression --input-file Cargo.lock --omit gzip --omit-levels 0 2 3 4 5 6 7 8
╭────────────────────┬───────────────────┬───────────────────────┬─────────────────────────╮
│ ┆ Best Ratio ┆ Best Compression Time ┆ Best Decompression Time │
╞════════════════════╪═══════════════════╪═══════════════════════╪═════════════════════════╡
│ Format ┆ Bzip2 ┆ Lz4 ┆ Lz4 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ Compression level ┆ 1 ┆ - ┆ - │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ Compression Ratio ┆ 4.56:1 ┆ 2.42:1 ┆ 2.42:1 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ Encode/decode time ┆ 2.36ms/686.34µs ┆ 83.29µs/32.53µs ┆ 83.29µs/32.53µs │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ Compressed Size ┆ 7.36 KiB [7533 B] ┆ 13.83 KiB [14163 B] ┆ 13.83 KiB [14163 B] │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ % of Original ┆ 21.94% ┆ 41.25% ┆ 41.25% │
╰────────────────────┴───────────────────┴───────────────────────┴─────────────────────────╯
==> Short summary
Best Compression Ratio: Bzip2[1] Compression/Decompression: 2.36ms/ 686.34µs 4.56:1 (21.94% of original)
Best Compression Time: Lz4 Compression/Decompression: 83.29µs/ 32.53µs 2.42:1 (41.25% of original)
Best Decompression Time: Lz4 Compression/Decompression: 83.29µs/ 32.53µs 2.42:1 (41.25% of original)
mDNS 工具
内置的 mDNS/DNS-SD 工具的目的是仅为了方便网络设置/测试/调试,因此它们通常比例如 avahi
更冗长,并且默认设置要慢得多(但更完整)。
发现服务
qft mdns discover --service-label googlecast --service-protocol tcp
输出示例
INFO Browsing for _googlecast._tcp.local.
INFO Resolved a new service: SERVICE_NAME._googlecast._tcp.local.
INFO Discovered 1 service!
Hostname: SERVICE_NAME.local.
Type Name: _googlecast._tcp.local.
Full Name: SERVICE_NAME._googlecast._tcp.local.
IP(s): fe80::d912:463a:8c88:deca
192.168.121.21
解析 mDNS 主机名
解析主机名IP(s),以下所有形式都是有效的。
qft mdns resolve foo
qft mdns resolve foo.local
qft mdns resolve foo.local.
输出示例
INFO Resolving address for foo.local.
Hostname: foo.local.
IP(s): fe80::d912:463a:8c88:deca
192.168.121.21
注册 mDNS 服务(用于测试或通过地址注册的主机名进行传输)
qft mdns register --hostname foo-name --service-label bar-label --service-protocol tcp --keep-alive-ms 123456
INFO Registering:
Hostname: foo-name.local.
Type: _bar-label._tcp.local.
Full Name: test_inst._bar-label._tcp.local.
INFO Keeping alive for: 123.456s
您可以使用 qft mdns
子命令或例如使用 avahi
来查找。
avahi-resolve --name foo-name.local
# foo-name.local 172.17.0.1
但它只输出第一个接收到的地址。使用 qft mdns resolve
将输出所有关联的IP。如果您需要速度,请使用 --short-circuit
标志,在解析与主机名关联的第一个IP后立即返回,例如。
qft mdns resolve foo-name[.local.] --short-circuit
支持的压缩格式
- bzip2
- gzip
- lz4
- xz
安装
从源代码构建(如果您已安装Rust工具链,则首选)。
cargo install quick-file-transfer
预构建的二进制文件
curl --proto '=https' --tlsv1.2 -sSf https://crambl.github.io/quick-file-transfer/install.sh | bash -s -- --to <DEST>
移除功能
目前有3个功能
- mdns
- ssh
- evaluate-compression
要从源代码安装并禁用所有功能,请运行
cargo install quick-file-transfer --no-default-features
要启用 ssh
和 mdns
功能,请运行
cargo install quick-file-transfer --no-default-features --features ssh,mdns
比较/基准测试
基准测试使用 hyperfine
默认设置进行。
使用附近的一个7.2 MiB的JSON文件(未美化)中的真实数据。
针对通过以太网连接到千兆网络的 Raspberry Pi Zero W
。
类似netcat的模式
RPI-0W运行 qft listen -p <PORT> --output 7mb.json
和 nc -l <PORT> > 7mb.json
在基准测试期间重复进行。
命令 | 平均值[ms] | 最小 [ms] | 最大 [ms] | 相对 |
---|---|---|---|---|
qft发送IP<IP> -端口<端口> -7MB.json |
895 ± 52 | 766 | 935 | 1.31 ± 0.11 |
qft发送IP<IP> -端口<端口> -7MB.json lz4 |
486 ± 60 | 404 | 584 | 1.03 ± 0.09 |
qft发送IP<IP> -端口<端口> -7MB.json gzip |
444 ± 120 | 325 | 685 | 1.00 |
nc-N<IP> <端口> <7MB.json |
1049 ± 8 | 1036 | 1056 | 1.42 ± 0.12 |
类似scp模式
命令 | 平均值[ms] | 最小 [ms] | 最大 [ms] | 相对 |
---|---|---|---|---|
qft ssh 7MB.json<用户>@<IP>:~/7MB.json |
2.295 ± 0.131 | 2.108 | 2.399 | 1.14 ± 0.10 |
qft ssh 7MB.json<用户>@<IP>:~/7MB.json lz4 |
2.004 ± 0.122 | 1.797 | 2.194 | 1.00 |
qft ssh 7MB.json<用户>@<IP>:~/7MB.json gzip4 |
2.026 ± 0.120 | 1.847 | 2.122 | 1.01 ± 0.09 |
scp 7MB.json<用户>@<IP>:~/7MB.json |
2.448 ± 0.039 | 2.404 | 2.532 | 1.22 ± 0.08 |
依赖关系
~5–20MB
~240K SLoC