65.9K
CodeProject 正在变化。 阅读更多。
Home

在协议级别暂停和恢复。(您可以用任何语言实现)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.64/5 (18投票s)

2002年10月10日

5分钟阅读

viewsIcon

200761

downloadIcon

5563

有没有想过一些流行的下载工具是如何能够中断下载、断开网络连接,然后在以后重新连接并从之前中断的地方继续文件传输的。

Sample Image - pauseresume.jpg

引言

有没有想过一些流行的下载工具和 FTP 客户端是如何能够中断下载、断开网络连接,然后在以后重新连接并从之前中断的地方继续文件传输的。我之前写的一个 FTP 客户端就想实现这个功能(看看这个),但我却一无所知。Microsoft 没有直接的 API 支持。我找到了一些第三方支持,但要花钱。所以,我到处搜寻,并写了自己的实现。我的方法可能不代表标准,但它适用于几乎所有的 FTP 服务器。

我过去一直在阅读这个网站上的内容,我认为是时候回馈了。因此,我决定将这些内容整理在一起,写下我的第一篇文章。如果我没做好,请随时问我问题 :)。我还准备了一个可用的 C++ 示例来演示我的想法。只要您能以某种方式向服务器发送和接收 FTP 命令,您就可以用任何您喜欢的语言来实现。如果您重新使用代码,我很乐意接受您的使用或修改,但如果您不署名,我也不强求。

目录

一些热身理论

如今,大多数 FTP 服务器都支持 RESTART (REST) 命令。 (请参阅此 W3C 链接,了解更多关于其他 FTP 命令的信息)。REST 命令的目的是告诉 FTP 服务器设置一个文件传输需要重新开始的标记点。

以编程方式开始下载、暂停然后再次恢复

举个例子,假设您正在下载一个文件:MyHugeFooFile.zip

  1. 通常,您会向 FTP 服务器发送一个 RETRIEVE (RETR) 命令来下载文件 MyHugeFooFile.zip。将从服务器接收到的数据存储到一个临时文件,例如 Temp_MyHugeFooFile.zip。因此,任何时候下载中断,临时文件的大小就是到目前为止已成功传输的 MyHugeFooFile.zip 的实际有效数据量。
  2. 假设突然 ISP 连接断开,或者 FTP 服务器宕机,或者您的 FTP 客户端崩溃,或者您手动停止了下载。
  3. 下次您想重新开始下载时,读取临时文件的大小 (即到目前为止已下载的有效数据量),并将文件指针移到临时文件的末尾,这样后续下载就会从末尾开始追加数据。
  4. 现在,向 FTP 服务器发送一个 REST 命令,并将临时文件的大小作为参数。 (一个典型的语法是 REST 250,如果临时文件的大小是 250)。FTP 服务器将发送一个类似“从字节 250 开始恢复…”的响应。
  5. 现在您可以再次发送 RETRIEVE (RETR) 命令来下载文件 MyHugeFooFile.zip,FTP 服务器将从字节偏移量 251 开始发送数据。
  6. 现在,您需要负责将来自服务器的数据追加到不完整的文件 Temp_MyHugeFooFile.zip 中,这样您就准备好了。
  7. 传输完成后,在 WINDOWS 上将临时文件重命名为实际文件名。使用 C++,这通常看起来像 RenameFile(Temp_MyHugeFooFile.zip, MyHugeFooFile.zip); 完成。

以编程方式开始上传、暂停然后再次恢复

对于上传场景,概念上您做的事情类似,但有几点不同:

  1. 首先发送一个 STORE 命令。
  2. 连接中断。
  3. 通过发送 SIZE 命令或使用您喜欢的任何方法来读取 FTP 服务器上不完整临时文件的大小,总有很多种方法。
  4. 将本地文件定位到从服务器接收到的大小处,这样您将从下一个位置开始读取和发送数据。
  5. 发送一个 REST 命令。这样 FTP 服务器将设置一个标记点,以便从 REST 命令中传递的位置开始追加数据。
  6. 再次发送 STORE。
  7. 完成后,在 FTP 服务器上重命名文件。一个典型的 winInet 函数将是 FtpRenameFile(hConnect, Temp_MyHugeFooFile.zip, MyHugeFooFile.zip),或者使用您喜欢的方法,例如直接发送 RENAME FROM (RNFR) & RENAME TO (RNTO),这些方法显然比 WinInet 快。
  8. 完成。

以编程方式确定特定的 FTP 服务器是否支持暂停和恢复。

三个简单的步骤

  1. 连接到 FTP 服务器后,尝试发送一个带有 0 (零) 作为参数的 REST 命令。
  2. 如果命令失败或服务器返回类似“命令不支持”的信息,则表示该服务器不支持暂停和恢复。
  3. 如果 FTP 服务器返回一个类似“从字节 0 开始恢复”的响应,则表示服务器支持暂停和恢复。

现在,如果您刚开始编写代码,您可能会问,如何向 FTP 服务器发送这些命令。答案有很多种。原始套接字是一种,WinInet 是另一种。在我的示例代码中,我使用了 WinInet 的 API FtpCommand 来直接向 FTP 服务器发送命令。

关于 C+ 示例

我用 VC++ 编写了这个示例,演示了如何使用 WinInet 来实现暂停和恢复。为了代码审查的目的,请不要在意我的编码风格,将其视为一个我不到一个小时就写出来的示例。代码几乎是不可重用的,只有这个想法是可重用的,所以我没有对其使用设置任何限制。首先构建并运行示例,不要忘记将其链接到随示例一起提供的 wininet.lib。

此示例演示了下载暂停和恢复下载的场景。当您运行示例时,单击下载按钮开始下载,并注意显示进度的进度条。中途停止,然后重新开始。请注意,下载将从上次停止的位置重新开始。单击开始,并根据需要多次单击,直到下载完成。请注意,下载是硬编码从 ftp://ftp.gnu.org/ 开始,文件始终是根目录下的 find-ls.txt.gz

示例本身是自我解释的,但如果您有任何疑问,请随时提问,我会尽我所知回答。

© . All rights reserved.