代码之家  ›  专栏  ›  技术社区  ›  Idan K

实现支持恢复的下载管理器

  •  11
  • Idan K  · 技术社区  · 15 年前

    根据我目前收集的信息,在发送http请求时,我需要添加一个带有键“Range”和值“bytes=startoff endoff”的头字段。然后服务器返回一个http响应,其中包含这些偏移量之间的数据。

    因此,我大致的想法是将文件拆分为每个文件允许的连接数,并为每个拆分部分发送一个具有适当“范围”的http请求。因此,如果我有一个4mb的文件和4个允许的连接,我会将文件拆分为4个,并有4个http请求,每个请求都有相应的“Range”字段。实现resume特性需要记住哪些偏移量已经下载,而不是请求那些偏移量。

    • 这样做对吗?
    • 如果web服务器不支持恢复怎么办?(我猜它会忽略“Range”,只发送整个文件)
    • 在发送http请求时,是否应该在范围内指定整个拆分大小?或者可以要求更小的零件,比如说每个请求1024k?
    • 读取数据时,我应该立即将其写入文件还是进行某种缓冲?我想写小块可能是浪费。
    • 如果我没有使用内存映射文件,我应该按允许的连接打开该文件吗?或者在需要写入文件时只需查找?(如果我真的使用内存映射文件,这将非常容易,因为我可以简单地有几个指针)。

    7 回复  |  直到 15 年前
        1
  •  7
  •   Piskvor left the building Rohit Kumar    15 年前

    关于请求/响应:

    对于Range-d请求,可以得到三种不同的响应:

    206 Partial Content -支持并可能继续;检查内容范围标头以了解响应的大小/范围
    200 OK -字节范围(“恢复”)不受支持,整个资源(“文件”)如下
    416 Requested Range Not Satisfiable -范围不正确(超过EOF等)

    内容范围通常为。看起来像这样: Content-Range: bytes 21010-47000/47022 ,即字节开始/结束/总计。

    检查 HTTP spec

        2
  •  4
  •   phimuemue    11 年前

    我不是C++专家,但是我曾经做过一个.NET应用程序,它需要类似的功能(下载调度,恢复支持,优先下载)

    我使用了微软的bits(后台智能传输服务)组件,它是用c语言开发的。windows update也使用bits。我之所以选择这个解决方案,是因为我觉得自己还不够优秀,不能自己编写这种级别的东西;-)

    尽管我不确定你是否能得到BITS的代码,但我认为你应该看看它的文档,这可能有助于你理解它们是如何实现的,体系结构,接口等等。

    http://msdn.microsoft.com/en-us/library/aa362708(VS.85).aspx

        3
  •  3
  •   Jesper Fyhr Knudsen    15 年前

    我不能回答你所有的问题,但这是我对其中两个问题的看法。

    块大小

    关于块大小,您应该考虑两件事:

    1. 它们越小,发送HTTP请求的开销就越大。

    我建议您使用较小的数据块。不过,你得做些测试,看看什么尺码最适合你。

    内存与文件

    您应该将数据块写入内存中的缓冲区,然后在缓冲区已满时将其写入磁盘。如果你要下载大文件,如果你的用户内存用完了,可能会给他们带来麻烦。如果我没记错,IIS在内存中存储小于256kb的请求,任何较大的请求都会写入磁盘,您可能需要考虑一种类似的方法。

        4
  •  3
  •   Piskvor left the building Rohit Kumar    14 年前

    除了跟踪标记段开始的偏移量和每个段的长度(除非您希望在恢复时计算偏移量,这将涉及对偏移量列表进行排序并计算两个偏移量之间的距离),您还需要检查服务器发送的HTTP响应的Accept Ranges头,以确保它是正确的支持使用范围标头。指定范围的最佳方式是“range:bytes=START\u BYTE-END\u BYTE”,您请求的范围包括START\u BYTE和BYTE END\u BYTE,因此由(END\u BYTE-START\u BYTE)+1个字节组成。

    根据您计划在下载时使用的控件,如果您有套接字级别的控件,您可以考虑至少每32K写入一次,或者异步写入数据。

    我不能对MMF的想法发表评论,但是如果下载的文件很大,那就不是一个好主意,因为你会消耗大量的RAM,最终甚至导致系统交换,这是不可能的

    关于块的处理,您可以只创建几个文件-每个段一个,可以选择预先分配磁盘空间,用块大小的\x00填充文件(预先分配可能会在下载期间为您节省一些时间,但会使下载开始变慢),然后最后只写入所有块按顺序进入最终文件。

    您应该注意的一点是,多个服务器有一个最大并发连接限制,并且您无法提前知道它,因此您应该准备好处理http错误/超时,并更改块的大小,或者创建一个块队列,以防创建的块数超过最大连接数。

        5
  •  2
  •   user377136 user377136    14 年前

    这并不是对最初问题的回答,但另一件值得一提的事情是,一个可恢复的下载程序在试图获取下一块可能已经更改的内容之前,还应该检查资源上最后修改的日期。

        6
  •  0
  •   hartmut hartmut    15 年前

    在我看来,你应该限制每个下载块的大小。如果连接在接近数据部分末尾时中止,大数据块可能会迫使您重复下载数据。特别是连接速度较慢的问题。