最近公司做一个基于智能客户端的项目,让用户在下载主程序后通过验证再下载配置文件和一个库(50多M),由于工作需要和兴趣我就请缨做一个多线程断点续传下载的组件.
      开始是每接收一次LOCK流 定位再写入磁盘.结果线程越多越慢,阻塞在写磁盘上了,数据还在系统的TCP缓冲区里,还容易超时,
看来得用一个后台线程写磁盘.分配一个大的内存块用来异步写磁盘
可又有个问题:缓存多大,怎么区分个各线程的数据,长度
再Seek到相应的位置写入
请教各位 有何妙策!
~~~~~~~~~~~~~~~~~~~~~~~~~~
别外 发现迅雷的多线程HTTP请求很奇怪
比如10个线程,文件长度为10000字节,
我用的是每个线程平均分一段range
线程1 range:0-999
线程2 range:1000-1999
.
.
.
线程10:range:9000-9999
而迅雷的请求是这样的
线程1:range :0-9999
线程2:range :1000-9999
线程3:range :2000-9999
.
.
.
.
线程10:range:9000-9999
是不是WEB服务器有缓存优化,最先到达的请求要返回的内容有缓存在内存中后面的请求直接从内存中发送给client
而迅雷的客户端每个线程只读取1000个字节??

解决方案 »

  1.   

    http://www.cnblogs.com/chiname/articles/179490.html
    LZ提供的经验太好了! 谢谢了!
      

  2.   

    http 协议规定可以这么传送,那么 httpServer 实现就是了。 至于是不是缓存,就要看 http Server 怎么做的,是不是呢?下载的文件的大小一开始是知道的,flashGet 就是开始的时候就分配磁盘空间,那么你只要对应地写到磁盘文件的对应位置好了。
      

  3.   

    flashGet似乎是写在内存先,再打在硬盘的吧?
      

  4.   

    而迅雷的请求是这样的
    线程1:range :0-9999
    线程2:range :1000-9999
    线程3:range :2000-9999
    .
    这样的好处是 服务器第二个线程速度几乎为0的时候,第一个线程还能将第二个线程的部分下载到。
    属于一个应用层次上的技巧吧
      

  5.   

    而迅雷的请求是这样的
    线程1:range :0-9999
    线程2:range :1000-9999
    线程3:range :2000-9999这就是迅雷占资源的根源?请教
      

  6.   

    开始是每接收一次LOCK流 定位再写入磁盘.结果线程越多越慢,阻塞在写磁盘上了,数据还在系统的TCP缓冲区里,还容易超时
    //这个问题你可以把文件打碎了写,也就是10个线程写10个文件,然后把这10个合并成一个
    //驴子好像就是这样
    看来得用一个后台线程写磁盘.分配一个大的内存块用来异步写磁盘
    可又有个问题:缓存多大,怎么区分个各线程的数据,长度
    //这个相对麻烦先,不过问题也很简单,缓存自己定义,每个线程我一般用100K-2M(根据网速)
    //过程特殊,要先建一个和要下载文件一边大的文件(内容用0填充),原因看下去就知道了
    //比如4个线程,每个线程的缓存是1M,文件是40M.每个线程下到1M后,写入文件
    //只需要开着临时文件的流 随时写入就可以了(以上这种方法不爱用,老得看着流的位置,麻烦)
    至于讯雷的
    //个人认为 通过HTTP下载,请求是从你要开始的位置到文件结束也是合理的,你要控制的只是要下多少,而不用担心到那结束
      

  7.   

    LZ的猜想基本正确,迅雷的下载基本也是逐线程覆盖的。其实断点下载是应该这样的,要不有可以因为一个range的原因导致文件下载不全,在初始分配的时候我想应该每个range都是平均分配字节的,然后随着下载的过程动态调整(这点还比较难,还没有实验成功过)...
      

  8.   

    重点是range的分配
    迅雷和flashget为什么不平均分配,
    都是
    range:xxxxxxx-
    这样服务器返回的不是多出来了吗?
      

  9.   

    而迅雷的请求是这样的
    线程1:range :0-9999
    线程2:range :1000-9999
    线程3:range :2000-9999不要因此就认为线程之间重复下载完整数据,这也太小看客户端程序了。下载线程并不需求超过一页的数据,它发这个参数上去但是仅仅有耐心等待一页数据下载,是完全可以的。
      

  10.   

    例如4K  -->  例如64K
      

  11.   

    服务器不但要限制线程数(Response.End),而且要限制速度(使用sleep)。这也是很简单的asp.net程序,大概不到50行代码就能报所有功能写好。这样的服务器端程序可以被通用的多线程客户端使用。当然你也可以自己规定自己的协议,完全没有必要遵循协议的head参数。
      

  12.   

    支持http1.1的web服务器都支持,其实就是服务器用多个线程向客户端发数据.
    while(Client.IsConnectd)
    {
       send range中请求的数据
    }
    我平均的话如果服务器不支持多线程,另一个线程可以一直重试,直到前一个线程下载完断开,这样后一个线程就可以连上了.
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    为了防止竟争对手等不怀好意的人狂下载,URL是肯定会被人知道的.
    占用服务器带宽.采用验证.用什么方案比较好
    就是只能通过客户端软件下载.软件中包含了用户信息.怎么验证?
    把用户信息加在post后进行验证.把用户信息sha1再发也不好可能被截获.......
    大侠有什么方案,分不够再加
      

  13.   

    这位兄弟,您是用SOCKET套接字来做,可以可以说一下,向服务器请求某个文件的某个范围的数据的命令?