TCP接続を介してディレクトリツリーをコピーしたいとします。ソース側は、すべてのファイルを再帰的に収集し、NetworkStream経由でシンク側に送信するために、ファイルシステムのどこかで開始する必要があります。ソースサイドでZIPファイルを作成してクライアントに送信できるように見えます。NetworkStream経由でアーカイブを転送する
- あり作成すべきではない一時ファイル
- メモリ内のすべてのファイルが作成されるべきではない
- データは、インバンドで送信する必要があります。しかし、いくつかの要件があります。
最初の2つの要件は、NetworkStream経由でZIPアーカイブを送信することで実現できます。 アクセス権の問題により一時ファイルを避ける必要があります。ディレクトリツリーには、膨大な量のデータが格納され、メモリ不足の問題を引き起こす可能性があります。 3番目の要件は少し複雑です。ソースとシンクの間に1つのTCP接続しか確立されていないはずです。
プロトコルは、ディレクトリ名のようなメタ情報の交換のために、データ転送の前に同じ接続を使用し、少なくとも成功した転送を確認し、データがファイルシステムに書き込まれたことを確認します。
私はすでにSharpZipLibを試しました。しかし、これはストリームを読むときに常に4キロバイトのチャンクを読み込みます。 ZIPアーカイブの終わりを識別するためにストリームの終わりが必要です。アーカイブはインバンドである必要があるため、これは不適切です。
DotNetZipライブラリのドキュメントには、シーク可能なストリームが必要であることが記載されています。ネットワークストリームでは利用できないものがあります。
このようなディレクトリ構造はどのように転送できますか?
は、ファイルデータが同じTCPストリームに埋め込まれている必要があることを明確にしました。
Windows用の 'tar'を試しましたか?サブプロセスとして起動しましたか?それはあなたが望むものを正確に行い、ディレクトリツリーをストリームに変換するために日常的に使用されます。さらに、それは両方向を行います。外部のコンプレッサーでパイプするか、C#の内部でストリームを圧縮することができます。私はまた、車輪を再発明しないことが良いことだと思います。 –
@EugenRieck接続ごとに新しいプロセスを作成するのは少し高価です。 (さらに、ディレクトリツリー内の各ファイルに対して512バイトのブロックを取得します。) – harper
はい、プロセスを生成するコストがあります。しかし、ディレクトリツリーを走査し、すべての単一のファイルを処理し、出力を圧縮し、最後にネットワーク経由で送信するコストと比較すると、きわめて小さいです。 512バイトのブロックサイズは、圧縮した後も簡単です。 –