意图
模拟迅雷等下载工具,将一个大文件拆分成多次请求。
条件
服务端资源地址必须支持范围请求。
判断是否支持的方法只需要看Responses Header中是否带有Accept-Ranges响应头。
Accept-Ranges 表明服务器是否支持指定范围请求及哪种类型的分段请求 Accept-Ranges: bytes
原理
涉及到的主要Request Header
Range: 只请求实体的一部分,指定范围 Range: bytes=500-999
If-None-Match: 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变
涉及到的主要Response Header
Accept-Ranges: 表明服务器是否支持指定范围请求及哪种类型的分段请求 Accept-Ranges: bytes
ETag: 请求变量的实体标签的当前值 ETag: “737060cd8c284d8af7ad3082f209582d”
Content-Length: 响应体的长度 Content-Length: 348
单线程主要流程:
第一步:发送一个HTTP HEAD请求,向服务器请求资源的响应头,判断是否支持范围请求。[若不支持,就不需要走下去了]
第二步:拿到资源的ETag值,以及Content-Length值,保存下来。
第三步:根据你一次想下载多少字节的数据,通过ContentLength计算出需要请求的总次数。
第四步:将需要请求的数据范围写到Range请求头中,发送请求。
第五步:保存数据到同一个文件。
第六步:若请求的次数还没完成,回到第四步,若完成了,结束进程。
多线程主要流程:
基本思路与单线程一致,区别在于多线程因为一次有多个请求同时发出,所以拿到的数据不一定与资源顺序一致,所以不能像单线程那样下载一部分,保存一部分。
基于上面的问题,我想到的解决方案是创建一个Dictionary对象,每次请求到数据将数据连同它对于的请求编号保存到队列中。当所以线程都结束后,调用写方法,将队列中的数据排序以后依次写入到文件当中。
代码实现
main:
SingleDemo.cs:
MultiDemo.cs:
源代码
源代码链接