11

我正在为游戏客户端开发一个更新程序,这样玩家在更新时就不必下载整个客户端。

现在,创建标准更新程序并不难,但是对于大文件来说却很慢。

客户端未压缩大约 1.5 GB,有大约 250 个文件。更新服务器上的文件经过 gzip 压缩并通过 HTTP 下载。

更新程序的工作方式如下:从服务器获取补丁列表 -> 将补丁列表中的文件与本地文件(crc32 / 文件大小)进行比较 -> 如果丢失/错误的文件大小/哈希不一样 -> 从服务器下载 gzip 压缩文件 -> 解压缩文件

更新程序最耗时的部分:为每个文件生成 crc32 哈希/下载大文件

我想到了一些可以加快速度的事情:

  • 类似 Rsync 的 diff 更新程序 - 这将加快下载速度,因为它只会获取文件的不同部分,而不仅仅是下载整个文件。这会很有帮助,因为通常客户端更新不会影响大文件的许多部分。但我想这将是某种矫枉过正。

  • 更好的压缩——当客户端被压缩时,Gzip 节省了大约 200 MB。我还没有尝试使用其他一些压缩方法,但我猜 bzip2、lzma 或其他方法会节省更多空间并加快下载速度。具有讽刺意味的是,它们会减慢文件的解压缩速度。

  • 其他文件检查方法 - 目前我正在使用 C# crc32 实现,因为它比标准 c# md5 实现更快。有没有更快的算法可以判断文件是否相同?

  • 版本系统 - 它实际上不会加速任何事情,但更新程序不必计算所有哈希值。如果用户愿意,它可以通过额外的“修复”功能检查所有文件与实际版本。

我应该使用这些解决方案中的哪一个,或者是否有任何我没有列出我应该使用的方法?

4

3 回答 3

2

压缩单个文件

您可以只下载新的或更改的文件,而不是下载整个包。

在客户端和服务器上存储哈希

通过预先计算您的哈希值,您可以节省大量时间。您的哈希比较步骤成为存储所有文件哈希的单个文件的差异。这在功能上与版本控制系统相同,但“版本”有点难以愚弄。用户很容易打开版本的纯文本文件并将数字设置为下一个版本以跳过补丁。如果你想防止这种行为,散列会稍微安全一些。

并行化

执行哈希文件的 diff 后,您可以将请求发送到服务器以获取需要下载的文件列表。然后,您的下载器可以连续流式传输每个文件,并且在收到文件后,其他线程可以解压缩并移动下载的文件。

于 2013-08-23T15:12:20.393 回答
1

另一种选择是存储已更改内容的增量而不是完整文件。然后,您只需下拉将文件“升级”到新版本所需的内容。查看http://xdelta.org/

于 2013-08-23T16:01:19.137 回答
1

我过去做过这件事,这实际上取决于您的具体实施和所需的选项。我们做了一些事情:

  • 允许用户选择“完整”扫描的偏好以进行每次更新。除非存在一些安全问题,否则您没有理由比较每个哈希值。
  • 在全面扫描中,如果需要,首先对纯文本文档或 XML 文档执行散列。我发现 XML 有助于与服务器进行匹配,以便仅检索必要的特定文件。
  • 如果这对您有用,您总是可以只对文件的“名称”而不是内容执行散列。我是什么意思?将 Directory.GetFiles() 结果与预期结果进行哈希运算,以查看是否需要进一步查找丢失的文件。如果您担心文件篡改并且实际上需要内容的哈希值,这显然不起作用。
于 2013-08-23T15:19:40.070 回答