PCEVA,PC绝对领域,探寻真正的电脑知识
开启左侧

Windows下是否有程序支持二进制流的标准输出

[复制链接]
haierccc 发表于 2019-8-21 23:55 | 显示全部楼层 |阅读模式
点击数:6434|回复数:20
本帖最后由 haierccc 于 2019-8-21 23:59 编辑

最近学了一款很有用的网络工具NetCat,以及其升级版Ncat。
在Linux下,可以使用标准输入和输出(STDIN/STDOUT)把压缩数据从a传送到B,非常方便:
host2$ncat -l | tar x zv
host1$tar czv <files> | ncat --send-only host2
Windows下也有CMD窗口,但弄了半天,愣是没有弄出来类似的情况。
WinRAR不支持标准输入输出,7-ZIP是支持,代码也在谷歌上找到了,目标输出也是压缩包。命令是:

发送端机器A:type hello.txt|7z a -an -txz -bd -si -so|ncat 192.168.1.2 4444 --send-only
接收端机器B:ncat -l 4444>abc.7z

这段代码的意思是,先把文本文件hello.txt的内容通过管道输入给7Z压缩(注意其中的-si,也就是”标准输入“),然后把压缩之后的数据传送到”标准输出“(注意其中的-so),而标准输出的接收者就是ncat,再将压缩后的数据流送到机器B,也就是192.168.1.4:4444。
这段代码是成了,但问题是dos命令:type hello.txt只能显示文本文件,显示二进制文件就乱套,无法把二进制文件输送给7Z。而且也只能显示一个文件。
Linux有CAT命令很方便,不知道DOS下怎样改动上述代码,能实现二进制文件的传输。
谢谢


Nospel 发表于 2019-8-22 00:48 | 显示全部楼层
每个字都认识,连在一起就读不懂了系列
尊称 发表于 2019-8-22 02:59 | 显示全部楼层
本帖最后由 尊称 于 2019-8-22 03:01 编辑

查了官网,7za        7-Zip 附加包:独立命令行、7z 程序库、Far 管理器插件

看命令行注释,直接用不就行了吗?干嘛还有type通道输入呢

7za a -an -txz -bd -so  help1.txt help2.xxx | ...
不要-si参数即可

7-Zip (a) 19.00 (x86) : Copyright (c) 1999-2018 Igor Pavlov : 2019-02-21

Usage: 7za <command> [<switches>...] <archive_name> [<file_names>...] [@listfile]

<Commands>
  a : Add files to archive
  b : Benchmark
  d : Delete files from archive
  e : Extract files from archive (without using directory names)
  h : Calculate hash values for files
  i : Show information about supported formats
  l : List contents of archive
  rn : Rename files in archive
  t : Test integrity of archive
  u : Update files to archive
  x : eXtract files with full paths

<Switches>
  -- : Stop switches and @listfile parsing
  -ai[r[-|0]]{@listfile|!wildcard} : Include archives
  -ax[r[-|0]]{@listfile|!wildcard} : eXclude archives
  -ao{a|s|t|u} : set Overwrite mode
  -an : disable archive_name field
  -bb[0-3] : set output log level
  -bd : disable progress indicator
  -bs{o|e|p}{0|1|2} : set output stream for output/error/progress line
  -bt : show execution time statistics
  -i[r[-|0]]{@listfile|!wildcard} : Include filenames
  -m{Parameters} : set compression Method
    -mmt[N] : set number of CPU threads
    -mx[N] : set compression level: -mx1 (fastest) ... -mx9 (ultra)
  -o{Directory} : set Output directory
  -p{Password} : set Password
  -r[-|0] : Recurse subdirectories
  -sa{a|e|s} : set Archive name mode
  -scc{UTF-8|WIN|DOS} : set charset for for console input/output
  -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files
  -scrc[CRC32|CRC64|SHA1|SHA256|*] : set hash function for x, e, h commands
  -sdel : delete files after compression
  -seml[.] : send archive by email
  -sfx[{name}] : Create SFX archive
  -si[{name}] : read data from stdin
  -slp : set Large Pages mode
  -slt : show technical information for l (List) command
  -snh : store hard links as links
  -snl : store symbolic links as links
  -sni : store NT security information
  -sns[-] : store NTFS alternate streams
  -so : write data to stdout
  -spd : disable wildcard matching for file names
  -spe : eliminate duplication of root folder for extract command
  -spf : use fully qualified file paths
  -ssc[-] : set sensitive case mode
  -sse : stop archive creating, if it can't open some input file
  -ssw : compress shared files
  -stl : set archive timestamp from the most recently modified file
  -stm{HexMask} : set CPU thread affinity mask (hexadecimal number)
  -stx{Type} : exclude archive type
  -t{Type} : Set type of archive
  -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options
  -v{Size}[b|k|m|g] : Create volumes
  -w[{path}] : assign Work directory. Empty path means a temporary directory
  -x[r[-|0]]{@listfile|!wildcard} : eXclude filenames
  -y : assume Yes on all queries

尊称 发表于 2019-8-22 03:03 | 显示全部楼层
本来想到copy xxx con呢,con还想了半天没想起来,网上搜索也半天才搜到,却不能这么用,con原来只是控制台,不是标准输入输出设备,测试失败
尊称 发表于 2019-8-22 03:09 | 显示全部楼层
代码也在谷歌上找到了


还谷歌上,官网不就有下载嘛  
尊称 发表于 2019-8-22 03:12 | 显示全部楼层
Linux是九十年代从unix发展出来的,当然它的命令是完整的,dos命令肯定不全,像是unix缩水版,呵呵
尊称 发表于 2019-8-22 03:31 | 显示全部楼层
本帖最后由 尊称 于 2019-8-22 11:49 编辑

其实文件的标准输入输出传输功能,简单的几行C代码就编成了,只是平常没人这么用。你自己编一个就是。
不对,不用管道,直接ncat 192.168.1.2 4444 --send-only  <hello.xxx,7z单独本地压缩就好了,winrar本地压缩


从流设备和块设备的效率看,通常流设备效率要低很多,尤其是现在多线程使用,尤其是二进制文件大数据量操作,压缩我想应该是这种状况。ncat采用流设备,正好适合网络传输,没必要非得拘泥于一种形式。
尊称 发表于 2019-8-22 03:51 | 显示全部楼层
本帖最后由 尊称 于 2019-8-22 03:57 编辑

其实最早实用于文件传输是超级终端,直接电话拨号或串口连接即可,甚至几千公里无有因特网,两电脑之间无需tcpip协议,有了tcpip协议,还有几个人这么用它呢?
haierccc  楼主| 发表于 2019-8-22 18:24 | 显示全部楼层
尊称 发表于 2019-8-22 02:59
查了官网,7za        7-Zip 附加包:独立命令行、7z 程序库、Far 管理器插件

看命令行注释,直接用不就行 ...

佩服高人!
那个7za是在哪下载的?
尊称 发表于 2019-8-22 18:49 | 显示全部楼层
haierccc 发表于 2019-8-22 18:24
佩服高人!
那个7za是在哪下载的?

上面链接                                          
haierccc  楼主| 发表于 2019-8-22 20:35 | 显示全部楼层
本帖最后由 haierccc 于 2019-8-23 23:35 编辑
尊称 发表于 2019-8-22 03:51
其实最早实用于文件传输是超级终端,直接电话拨号或串口连接即可,甚至几千公里无有因特网,两电脑之间无需 ...

用你的代码,再经过烧脑的研究,得出结论如下。
在A机器,一个文件先经过压缩,然后传递至B机器,在B端自动解压缩。
同时因为有--send-only参数的存在,发送和接受过程完毕后,两端都自动退出ncat,整个过程对用户是透明的:
A机器(发送端)代码:7za a -tgzip -an -so 1.txt|ncat 192.168.1.2 --send-only
B机器(接受端)代码:ncat -l|7za x -tgzip -bd -y -si
于是在B机器得到1.txt,very good!

然后,就想多文件传输,于是在1.txt后面加入2.txt:7za a -tgzip -an -so 1.txt 2.txt|ncat 192.168.1.2 --send-only
结果是报错,经过研究发现,gzip、bzip2、xz的压缩包,仅仅支持单文件!
没错,就是说一个压缩包里面只能有1个文件。而且只有gzip格式能正常在B端以原始文件名解压缩。
那么7z呢?7z又不支持STDIN和STDOUT。
那么好,就用批处理的for循环发送:
A机器(发送端)代码:for %t in (*.txt) do  7za a -tgzip -an -so %t|ncat 192.168.1.2 --send-only
B机器(接受端)代码:ncat -l --keep-open |7za x -tgzip -bd -y -si
以上语句的含义是,A端读入当前目录的所有txt文件挨个发送到B端,B端用参数--keep-open防止接收到一个文件就自动退出。
看似完美,因为A端的确是发送了所有的txt文件,可问题就是。。。B端只看到了这些txt文件当中的第一个文件名,而其内容,是A端所有txt文件的累加!
这是因为B端的7za居然不知道A端的单个压缩文件是否发送完毕,它们当作一个连续的数据流,都累加到第一个收到的文件里,直到在B端手工退出ncat。
原因可能是gzip本来也就是支持单文件,所以无需分割文件。
由此,我的压缩批量发送多个文件的实验失败了。
不知道你是否有更好的办法完成。

其实有另一个办法,这是从Linux抄过来的,既然Linux用到了tar,那我就用tar for windows:
A机器(发送端)代码:tar -cv *.exe|ncat --send-only 192.168.1.2
B机器(接受端)代码:ncat -l |tar -xvf -
这就把当前目录下的*.exe发动到了B,但没压缩只是打包归档。
=================================================

问题解决。
可以用2种方法压缩之后传输:
方法1:用7za压缩/解压:
发送端:tar -cv ?.txt|7za a -tgzip -an -so -si|ncat 192.168.1.2 --send-only
接收端:ncat -l|7za x -tgzip -bd -y -si -so|tar -xvf - -C /tmp
解释:发送端用tar把文件一个一个打包(不压缩)再喂给7za,7za一个一个的压缩这些包,再喂给ncat再发送出去;
接收端的ncat把接收到的压缩数据喂给7za解压成tar包,再喂给tar解包写入磁盘。

方法2:用bzip2压缩/解压:
发送端:tar -cv ?.txt|bzip2|ncat 192.168.1.2 --send-only
接收端:ncat -l|bzip2 -d|tar -xvf - -C /tmp
解释:原理一样,只是换了压缩程序。

tar for windows:http://gnuwin32.sourceforge.net/packages/gtar.htm
7za for windows:https://www.7-zip.org/a/7za920.zip
bzip2 for windows:http://gnuwin32.sourceforge.net/packages/bzip2.htm

如何证明数据已经被压缩传输了?
Tar的 -cv 参数仅仅是多文件打包,并没有压缩。

打包之后不经过压缩就发送,用Wireshark抓包能发现经Tar的打包的数据,虽然加了包头包尾,但被传输文件的数据并没有变。
比如1.txt的内容是ABCDKKAAAAAAAAAAAAAAAAAA,命令如下:
发送端:tar -cv 1.txt|ncat --send-only 192.168.1.2
接收端:ncat -l>1.tar
wireshark抓到的tcp数据(节选):
无标题1.png
但经过7za和bzip2压缩的数据,在tcp里无论如何找不到1.txt的内容了。



另一种证明方法,就是找一个大文件压缩发送,然后看网卡的“已发送”字节数与文件体积之比。
于是找来体积又大,又容易被压缩的虚拟磁盘文件做实验:
1.png 2.png
事实证明,比例是3:8。
Nospel 发表于 2019-8-22 20:58 | 显示全部楼层
本帖最后由 Nospel 于 2019-8-22 21:05 编辑
haierccc 发表于 2019-8-22 20:35
用你的代码,再经过烧脑的研究,得出结论如下。
在A机器,一个文件先经过压缩,然后传递至B机器,在B端自 ...

换个思路呢。想起sftp是默认可传二进制数据的,摸摸看有门路没

很多文件可压缩比例已经不大或很小了,再过一遍7zip也减不了多少肥

话说你局域网是带宽有多不足?不如换换带宽高的设备。非得要用芦苇管去抽水库么?
haierccc  楼主| 发表于 2019-8-22 21:34 | 显示全部楼层
本帖最后由 haierccc 于 2019-8-23 19:36 编辑
Nospel 发表于 2019-8-22 20:58
换个思路呢。想起sftp是默认可传二进制数据的,摸摸看有门路没

很多文件可压缩比例已经不大或很小了,再 ...

找时间研究。
研究这个是为了好玩,也是为了技术,想看看Linux下的功能是否能在Windows下实现。
话说终于实现了。
haierccc  楼主| 发表于 2019-8-23 19:17 | 显示全部楼层
Nospel 发表于 2019-8-22 20:58
换个思路呢。想起sftp是默认可传二进制数据的,摸摸看有门路没

很多文件可压缩比例已经不大或很小了,再 ...

问题解决啦!   
haierccc  楼主| 发表于 2019-8-23 19:17 | 显示全部楼层
尊称 发表于 2019-8-22 02:59
查了官网,7za        7-Zip 附加包:独立命令行、7z 程序库、Far 管理器插件

看命令行注释,直接用不就行 ...

问题解决啦!   
Nospel 发表于 2019-8-23 21:09 | 显示全部楼层

接下来的挑战是:A机选中 a 个文件夹(内含 b 个多层级子文件夹及其内共计 c 个混合类型文件 )与 d 个混合类型文件,鼠标一次性拖到一个批处理文件上,放开;B机收到压缩后数据流完毕后自动解压,还原甲机传输内容且保持数据无误、结构不变
举个栗子,把A机上一个绿色版 Program Files\Photoshop\ 下的所有文件和文件夹选中,拖到批处理文件上放开,B机接收完压缩后数据流解压出来的东西里,直接双击Photoshop.exe就能运行


Pale_Cheung 发表于 2019-8-28 14:01 | 显示全部楼层
方便但不安全,明文传输明白吧,当然有很多管道可以加密。还有直接加密传输的命令,比如ssh


windows下有 https://www.cygwin.com/
实现 子系统

windows 10 也有 原生的 linux 子系统。

haierccc  楼主| 发表于 2019-8-28 19:34 | 显示全部楼层
Pale_Cheung 发表于 2019-8-28 14:01
方便但不安全,明文传输明白吧,当然有很多管道可以加密。还有直接加密传输的命令,比如ssh

是在一个Linux环境里,用Linux命令是吧
不会Linux,真是处处受限啊。

Pale_Cheung 发表于 2019-8-30 14:18 | 显示全部楼层
haierccc 发表于 2019-8-28 19:34
是在一个Linux环境里,用Linux命令是吧
不会Linux,真是处处受限啊。

一个是 windows 下的模拟
另外是 轻量级虚拟机(微软的原生)挂载windows的盘
haierccc  楼主| 发表于 2019-8-30 16:45 | 显示全部楼层
Pale_Cheung 发表于 2019-8-30 14:18
一个是 windows 下的模拟
另外是 轻量级虚拟机(微软的原生)挂载windows的盘
...

没明白,请明示
指的是Hyper-v虚拟机么

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部