#文件传输 #mdns #命令行 #压缩等级 #数据传输 #dnssd #网络

bin+lib quick-file-transfer

在本地网络主机之间快速、安全、轻松地传输文件

12 个版本 (破坏性更新)

0.10.2 2024 年 7 月 21 日
0.9.0 2024 年 7 月 13 日

#264网络编程

Download history 228/week @ 2024-06-13 198/week @ 2024-06-20 308/week @ 2024-06-27 82/week @ 2024-07-04 405/week @ 2024-07-11 128/week @ 2024-07-18 62/week @ 2024-07-25 10/week @ 2024-08-01

每月 208 次下载

MIT 许可证

180KB
4K SLoC

目录表↗️

快速文件传输

qft


目的

注意!这是一个正在进行中的项目,并不适合生产环境

在本地网络中尽可能快速、安全、轻松地传输文件。

此说明文档也以书籍的形式提供。

qft 优化了嵌入式系统在本地网络中定期传输大文件的场景,例如持续集成管道中固件(例如 Rauc)传输,这些工具包括 rsyncscpnetcat(注意:不要以此方式升级 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。
  • bashelvishfishpowershellzsh 提供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')

演示

evaluate-compression demo

输出示例

评估 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

要启用 sshmdns 功能,请运行

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.jsonnc -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