1

在我目前正在进行的一个 C# 项目中,我们试图通过网络计算大量文件的 MD5(当前 pot 是 270 万,client pot 可能超过 1000 万)。随着我们正在处理的文件数量,速度是一个问题。

我们这样做的原因是为了验证文件是否被复制到不同的位置而没有修改。

我们目前使用下面的代码来计算一个文件的MD5

MD5 md5 = new MD5CryptoServiceProvider();
StringBuilder sb = new StringBuilder();

byte[] hashMD5 = null;

try
{
   // Open stream to file to get MD5 hash for, create hash
   using (FileStream fsMD5 = new FileStream(sFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
      hashMD5 = md5.ComputeHash(fsMD5);
}
catch (Exception ex)
{
   clsLogging.logError(clsLogging.ErrorLevel.ERROR, ex);
}

string md5sum = "";
if (hashMD5 != null)
{
   // Change hash into readable text
   foreach (byte hex in hashMD5)
      sb.Append(hex.ToString("x2"));
    md5sum = sb.ToString();
}

然而,这个速度并不是我的经理所希望的。我们已经对我们计算 MD5 的方式和文件数量进行了许多更改(即,我们不会对我们不复制的文件这样做......直到今天我的经理改变了主意,所以所有文件都必须有一个为它们计算的 MD5,以防将来某个客户希望对我们的程序进行窃听,所以我猜所有文件都被复制)

我意识到网络速度可能是一个主要因素(100Mbit/s)。有没有一种有效的方法来计算网络上文件内容的 MD5?

提前致谢。特雷弗·沃森

编辑:将所有代码放在块中,而不仅仅是其中的一部分。

4

3 回答 3

3

瓶颈是整个文件必须通过网络进行流式传输/复制,而且您看起来不错......不同的哈希函数(md5/sha256/sha512)具有几乎相同的计算时间

这个问题的两种可能的解决方案:

1)在远程系统上运行哈希并将哈希存储到单独的文件中 - 如果在您的环境中可能的话。

2)创建文件的部分散列,以便您只复制文件的一部分。我的意思是这样的:

part1Hash = md5(file.getXXXBytesFromFileAtPosition1)
part2Hash = md5(file.getXXXBytesFromFileAtPosition2)
part3Hash = md5(file.getXXXBytesFromFileAtPosition3)
finalHash = part1Hash ^ part2Hash ^ part3Hash;

您必须测试文件的哪个部分最适合阅读,因此哈希值保持唯一。

希望有帮助...

编辑:更改为按位异或

于 2011-01-19T22:39:11.520 回答
3

一种可能的方法是使用 .Net 4.0 中的并行任务库。100Mbps 仍将是一个瓶颈,但您应该会看到适度的改进。

去年我写了一个小应用程序,它遍历文件夹树的顶层检查文件夹和文件安全设置。在 10Mbps WAN 上运行大约需要 7 分钟才能完成我们的一个大文件共享。当我并行化操作时,执行时间下降到 1 分钟多一点。

于 2011-01-19T22:42:37.750 回答
1

为什么不尝试在每个侦听端口的“客户端”上安装一个“客户端”,并在收到信号时为请求的文件计算 MD5 哈希值。

然后主服务器将只需要要求每个客户端计算 MD5。使用这种分布式方法,您将获得所有客户端的综合速度并减少网络拥塞。

于 2011-01-19T22:30:28.850 回答