2012-02-13 81 views
0

我想通過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

回答

0

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

要解決這個問題,只需將NetworkStream包裝在作爲DotNetZip一部分提供的CountingStream中。如果你這樣做,你應該可以使用ZipOutputStream就好了。

作爲替代方案,如果您不需要壓縮,則可以創建自己的tar類協議。

喜歡的東西

  • 4個字節的文件名的長度,包括路徑(M)
  • 8個字節的文件的長度(N)
  • M個字節的文件名(包括路徑),則使用UTF-8
  • N個字節的文件本身

前每個文件的內容進行編碼。