在 Netcat 中一次接收多个文件而不覆盖最后一个文件

在 Netcat 中一次接收多个文件而不覆盖最后一个文件

1 台机器监听(linux),而多个客户端(windows)在同一个监听端口上向其发送文件。Netcat 使用 -k 标签串行接收文件。

Listening machine: 
  nc -lp PORT -k > fileX
Clients: 
  nc IP PORT < file??

我想要的是从多个来源接收多个文件,并且不让它们互相覆盖。

请查看前面的命令。监听器机器始终将输出写入 fileX,从而覆盖了前一个客户端的文件。

我希望能够以某种方式更改每个不同客户端的输出文件名。客户端能否以某种方式通过 netcat 发送字符串“file10”,从而告诉侦听器输出到 > file10 ?

谢谢。

编辑:想出了一个主意:

这是通过脚本自动完成的:

  1. 首先,监听器将输出文件设置为file.txt。(nc -lp PORT > file.txt)

  2. 客户端通过 netcat 发送字符串(例如“file123”)。(这将是将来要发送的文件的文件名。)

  3. 侦听器写入 file.txt,然后读取 file.txt,并使用输出文件 > file123 启动新的 netcat 侦听器

  4. 最后,客户端发送数据。

答案1

其他答案讨论了拥有自定义协议/设置的意义。我不会重复。我假设你的自己的解决方案就是您想要的。

nc -k不是接收“来自多个来源的多个文件”的最佳工具,因为它仅在当前连接终止后才会监听另一个连接。这意味着它将接收多个文件,但会逐个接收,而不是并行接收。您的“多个来源”将相互阻塞。

socatreuseaddr可能fork会更好。

为了证明概念,我们来创建(在一个快速而肮脏方式)我们的自定义协议。文件将作为包含以下内容的流进行传输:

  1. 接收端使用的文件名或路径(不带换行符);
  2. 单个换行符(\n,LF,0x0a)作为分隔符;
  3. 二进制数据;
  4. 结束。

这是接收命令:

socat TCP-LISTEN:50011,reuseaddr,fork SYSTEM:'read -r f && cat >"$f"'

(编辑)这是通用接收命令,可\r从文件名中删除尾随部分(如果有)(对于不完全符合协议的 Windows 客户端很有用):

socat TCP-LISTEN:50011,reuseaddr,fork SYSTEM:'read -r f && f="${f%$(printf "\r")}" && cat >"$f"'

(编辑到此结束)。

发送文件:

(echo "The new name.foo" && cat "./the file to send.bar") > /dev/tcp/192.168.22.33/50011

笔记:

  • 50011是TCP端口号,你可以自己选择;
  • 192.168.22.33是服务器的地址,请更改它以匹配您的设置;
  • 我使用了/dev/tcp/…/…在 Bash 中有效的语法,nc如果您想要/需要的话,可以使用管道;
  • 文件名冲突仍然是一个问题,您需要一些脚本逻辑(而不是简单的cat)来解决它们;
  • SYSTEM有其局限性(参见man socat);不要将一些大型脚本主体传递给它,而是将脚本写入文件并运行该文件;您还可以调查EXEC
  • 我们的协议(快速而粗糙)不提供任何方式让服务器向客户端报告错误(如果有)或成功。

我使用 Debian 接收器和 Ubuntu 发送器对此进行了测试。有一次,三个不同的连接从两个不同的 IP 地址传输三个不同的文件。所有传输完成后,md5sum用于验证副本是否正确(最有可能的) 与原件相同;它们是。

答案2

不,普通的 netcat 没有这样的特殊命令。它不解释其输入,实际上它甚至不知道其输入/输出是一个文件:重定向由您的 shell 完成,netcat 不会费心查找。

因此你需要一个额外的程序解释收到的输入并自行打开输出文件。最后,您实际上会重新发明tar。(或者cpio,或者其他十几种类似格式。)

[client] tar -cf - fileXYZ | nc <ip> <port>
[server] nc -lp <port> | tar -xvf -

GNU 有 Windows 版本柏油并且 Win10 最近开始包括布斯达如果两者都不可用,则必须创建自己的协议 - 例如将文件名作为第一行发送,然后发送数据;您需要为发送方编写自定义代码对于接收者来说。

将括号中的多个命令分组为单个管道单元将有助于:

[client] (echo fileXYZ && type fileXYZ) | nc <ip> <port>
[server] nc -lp <port> | (read name; name=${name##*/}; name=${name%$'\r'}; cat > "$name")

但是相反,我会在 Linux 机器上设置 Samba 并配置一个公共共享,以便客户端可以简单地copy fileXYZ \\<ip>\incoming\fileXYZ

相关内容