导航
  • 主页
  • .NET Framework
  • ASP
  • Web Services
  • .NET互联网桌面应用
  • VB
  • 图表区
  • 分析与设计
  • 组件/控件开发
  • AppLauncher
  • 问答

C#HTTP多线程断点续传下载,关于迅雷的HTTP请求中的range标头的疑问

clamlp 2006-12-14 10:53:06
最近公司做一个基于智能客户端的项目,让用户在下载主程序后通过验证再下载配置文件和一个库(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个字节??
...全文
2055 1 收藏 25
写回复
25 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
billnie 2006-12-30
这位兄弟,您是用SOCKET套接字来做,可以可以说一下,向服务器请求某个文件的某个范围的数据的命令?
回复
hnsjack 2006-12-21
要分麳了.呵呵.以后清多多指教
回复
clamlp 2006-12-20
支持http1.1的web服务器都支持,其实就是服务器用多个线程向客户端发数据.
while(Client.IsConnectd)
{
send range中请求的数据
}
我平均的话如果服务器不支持多线程,另一个线程可以一直重试,直到前一个线程下载完断开,这样后一个线程就可以连上了.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
为了防止竟争对手等不怀好意的人狂下载,URL是肯定会被人知道的.
占用服务器带宽.采用验证.用什么方案比较好
就是只能通过客户端软件下载.软件中包含了用户信息.怎么验证?
把用户信息加在post后进行验证.把用户信息sha1再发也不好可能被截获.......
大侠有什么方案,分不够再加
回复
“平均”似乎太技术化了,服务器端不知道两个重复地址的请求是否应该拒绝,此时仍然需要控制总线程数量。看起来“平均”有点过分复杂化了。
回复
对服务器来说,不用平均,控制线程数量是一样可以保证最高效率的。
回复
clamlp 2006-12-20
磁盘缓存已经解决了.
是可以 ,我可以在线程中统计下载到多少字节后关闭连接
他为什么不平均,这样下载速度有更快吗?
回复
服务器不但要限制线程数(Response.End),而且要限制速度(使用sleep)。这也是很简单的asp.net程序,大概不到50行代码就能报所有功能写好。这样的服务器端程序可以被通用的多线程客户端使用。

当然你也可以自己规定自己的协议,完全没有必要遵循协议的head参数。
回复
多线程下载协议就是这样设计的,为的是可靠性。服务器带宽、流量大是什么意思?可以限制线程数据呀,例如每个IP只能最多5个线程。
回复
clamlp 2006-12-20
楼上的,服务器是我公司的呀.这样服务器的带宽,流量不是大了吗?
并发量就小了
回复
例如4K --> 例如64K
回复
而迅雷的请求是这样的
线程1:range :0-9999
线程2:range :1000-9999
线程3:range :2000-9999

不要因此就认为线程之间重复下载完整数据,这也太小看客户端程序了。下载线程并不需求超过一页的数据,它发这个参数上去但是仅仅有耐心等待一页数据下载,是完全可以的。
回复
客户端向服务器端请求从某个起点开始读数据,然后当读取的数据大于一页(例如4K),就中断连接,多于一页的字节丢弃掉,然后把数据保存到磁盘上。

服务器端根据客户端的起点开始下载数据,也是一页一页下载的,每下载一页都要判断是否客户端还在线,如果不在线,则停止输出。

在这个方案中,客户端的页面大小和服务器端的页面大小完全可以不一样,这具有很好的灵活性性。因此,服务器端不知道客户端的页面大小,只要客户端在线,就按照自己的页面大小一直属处下去,从请求点到文件结尾。
回复
kicck 2006-12-20
基本所有的数据流都是先写在内存中.再写到磁盘上吧...没有一个是接收过来就向文件中写吧.

如果真是这样倒还麻烦多了
回复
clamlp 2006-12-18
重点是range的分配
迅雷和flashget为什么不平均分配,
都是
range:xxxxxxx-
这样服务器返回的不是多出来了吗?
回复
zlkingdom 2006-12-17
LZ的猜想基本正确,迅雷的下载基本也是逐线程覆盖的。其实断点下载是应该这样的,要不有可以因为一个range的原因导致文件下载不全,在初始分配的时候我想应该每个range都是平均分配字节的,然后随着下载的过程动态调整(这点还比较难,还没有实验成功过)...
回复
CCjian 2006-12-16
学习
回复
fish_yht 2006-12-16
来学习的
回复
cangwu_lee 2006-12-15
http 协议规定可以这么传送,那么 httpServer 实现就是了。 至于是不是缓存,就要看 http Server 怎么做的,是不是呢?

下载的文件的大小一开始是知道的,flashGet 就是开始的时候就分配磁盘空间,那么你只要对应地写到磁盘文件的对应位置好了。
回复
balenoww 2006-12-15
UP
回复
zhaochong12 2006-12-15
http://www.cnblogs.com/chiname/articles/179490.html


LZ提供的经验太好了! 谢谢了!
回复
发动态
发帖子
.NET技术社区
创建于2007-09-28

5.8w+

社区成员

.NET技术交流专区
申请成为版主
社区公告
暂无公告