通过NetworkStream传输档案

问题描述:

我想通过TCP连接复制目录树。源端应在文件系统的某处启动,以递归方式收集所有文件,并通过NetworkStream将其发送到接收端。这看起来不知何故,因为我可以在源端创建一个ZIP文件并将其发送给客户端。但也有一些要求:通过NetworkStream传输档案

  • 不应该有任何创建临时文件
  • 应该不会在内存中创建任何文件
  • 的数据应该在带内发送。

前两个要求可以通过NetworkStream发送ZIP压缩文件来实现。 由于访问权限问题,应避免临时文件。目录树可能包含大量可能导致内存不足问题的数据。 第三个要求有点复杂。源和宿之间应该只建立一个TCP连接。

该协议在数据传输之前使用相同的连接来交换元信息,例如目录名称,并在数据传输后至少应答成功传输并且数据已写入文件系统。

我已经试过SharpZipLib。但是,当读取数据流时,总是读取4 KB的数据块。它需要流结束才能识别ZIP归档文件的结尾。这是不合适的,因为存档应该是带内的。

DotNetZip库文档提到它需要一个可寻找的流,什么不可用于NetworkStream。

这样的目录结构如何传输?

编辑阐明了文件数据必须嵌入在同一个TCP流中。

+0

您是否尝试过使用Windows的“tar”,将其作为子进程启动?它正是你想要的,并且经常用来将dir-tree转换成流。另外它可以确定两个方向。你可以通过一个外部压缩器来管它,或者压缩C#中的流。我也认为不重新发明轮子是件好事。 – 2012-02-13 13:38:00

+0

@EugenRieck为每个连接生成一个新进程有点贵。 (进一步,我会得到目录树中每个文件的512字节块。) – harper 2012-02-13 13:54:42

+0

是的,产生一个进程的代价是。但与遍历目录树,处理每个文件,压缩输出并最终通过网络发送的成本相比,这是微不足道的。在压缩之后,512字节的块大小是不容易的。 – 2012-02-13 14:07:34

你说得对,DotNetZip似乎不直接支持不可查找的流。但它需要的唯一原因是因为它需要知道Position,哪些不可查找的流不支持。

要解决这个问题,只需将NetworkStream包装在作为DotNetZip一部分提供的CountingStream中。如果你这样做,你应该可以使用ZipOutputStream就好了。

作为替代方案,如果您不需要压缩,则可以创建自己的tar类协议。

喜欢的东西

  • 4个字节的文件名的长度,包括路径(M)
  • 8个字节的文件的长度(N)
  • M个字节的文件名(包括路径),则使用UTF-8
  • N个字节的文件本身

前每个文件的内容进行编码。