前言

当下载电影时,我常常会想中断下载后,为什么点击开始时会在中断的地方继续下载呢?
又或者在看在线电影时,为什么可以按着播放条拖动就能看到想看的片段呢?

http的range请求将解决以上困惑。

多线程、断点续传、随机点播等的场景的步骤

1、客户端明确任务:从哪开始下载

  • 本地是否已有部分文件:文件已下载部分在服务器端发生改变?
  • 使用几个线程并发下载

2、下载文件的指定部分内容
3、下载完毕后拼装成统一的文件

HTTP Range规范

在RFC7233中有详细介绍
1、允许服务器基于客户端的请求只发送响应包体的一部分给到客户端,而客户端自动将多个片段的包体组合成完整的体积更大的包体。

  • 支持断点续传
  • 支持多线程下载
  • 支持视频播放器实时拖动

2、服务器通过Accept-Range头部表示是否支持Range请求

  • Accept-Ranges = acceptable-ranges
  • 例如:
    Accept-Ranges: bytes: 支持;
    Accept-Ranges: none: 不支持

Range请求范围的单位

基于字节为单位的时候,举例:设置响应体长度为10000

  • 第1个500字节:
    bytes=0-499 // 从0开始
  • 第2个500字节:
    bytes=500-999
    bytes=500-600, 601-999
    bytes=500-700, 601-999
  • 最后1个500字节
    bytes=-500
    bytes=9500-
  • 仅要第一个和最后一个字节:bytes=0-0, -1

通过Range头部传递请求范围,如:Range: bytes=0-499

测试

下面用一些小例子有测试一下。
用node搭了一个简单的服务器,返回的数字是22个字节的响应体

'Hello World 0123456789';

现在用curl命令获取全部的响应体,然后访问0-5的字节段:

-H参数添加 HTTP 请求的标头。
上面的命令就是添加HTTP头Range: bytes=0-5。
返回的是Hello (加上空格)一共六个字节。

现在获取第21个字节及以后的字节段,就可以用20-:


返回的是89

Range条件请求

  • 如果客户端已经得到了Range响应的一部分,并想在这部分响应未过期的情况下,获取其他部分的响应
    常与If-Unmodified-Since或者If-Match头部共同使用
  • If-Range = entity-tag / HTTP-date
    可以使用Etag或者Last-Modified

测试

下面用etag测试一下Range条件请求

首先获取0-5字节段

然后用-I来看看生成Hello 时服务器生成Etag的值

接下来,用这个值放到If-Match中获取6-10字节段:World

如果Etag发生了变化,来看看结果会怎么样,将最后的0改为1


返回412 Precondition Failed

结论

通过条件请求可以判断两次下载之间,服务器端资源有没有发生变化。如果发生了变化,就可以通过412这个响应知道,资源已经发生了变化。

服务器响应

如果只获取部分的body,那么服务器端返回的响应码不是200,而是206。
206 Partial Content

  • Content-Range头部:显示当前片段响应体在完整包体中的位置

  • Content-Range = byte-content-range / other-content-range
    { btye-content-range = bytes-unit SP (byte-range-resp / unsatisfied-range)
    byte-range-resp = byte-range '/' (complete-length / '')
    complete-length = 1
    DIGIT // 完整资源的大小,如果未知则用*号替代
    bytr-range = first-byte-pos "-" last-byte-pos }

  • 例如:
    1、Content-Range: bytes 42-1233/1234
    2、Content-Range: bytes 42-1233/*

测试

用一个视频播放的例子来看看206响应的样子。 

416 Range Not Statisfiable

  • 请求范围不满足实际资源的大小,其中Content-Range中的complete-length显示完整响应的长度,例如
    Content-Range: bytes */1234

测试

如果获取范围超出实际资源的大小,比如获取30-40。返回416

200 OK

  • 服务器不支持Range请求时,则以200返回完整的响应包体

多重范围与multipart

  • 请求:
    Range: bytes=0-50, 100-150
  • 响应:
    Content-Type: multipart/byteranges; boundary=...

测试

获取5-10, 10-15片段。

总结

1、客户端通过Range头部传递请求范围

2、服务端返回Accept-Range头部表示是否支持Range请求。

3、客户端如果在得到Range响应的一部分,并想在这部分响应未过期的情况下,获取其他部分的响应,可以用If-Range头部使用Etag或者Last-Modified为值。

4、只获取部分的body,服务器返回206响应码,其中Content-Range头部显示当前片段响应体在完整包体中的位置

5、客户端想多重范围下载资源,在Range头部的格式为Range: bytes=0-50, 100-150...(用逗号分隔)
响应头部Content-Type: multipart/byteranges; boundary=...

作者: zhangwinwin
链接:Http系列:断点续传与多线程下载
来源:github

Http系列:断点续传与多线程下载的更多相关文章

  1. 图解:HTTP 范围请求,助力断点续传、多线程下载的核心原理

    题图:by Charles Loyer 一.序 Hi,大家好,我是承香墨影! HTTP 协议在网络知识中占据了重要的地位,HTTP 协议最基础的就是请求和响应的报文,而报文又是由报文头(Header) ...

  2. 网络编程之PC版与Android手机版带断点续传的多线程下载

    一.多线程下载         多线程下载就是抢占服务器资源         原理:服务器CPU 分配给每条线程的时间片相同,服务器带宽平均分配给每条线程,所以客户端开启的线程越多,就能抢占到更多的服 ...

  3. ASP.NET文件下载各种方式比较:对性能的影响、对大文件的支持、对断点续传和多线程下载的支持

    asp.net里提供了多种方式,从服务器端向客户端写文件流,实现客户端下载文件.这种技术在做防下载系统时比较有用处.主些技术主要有:WriteFile.TransmitFile和BinaryWrite ...

  4. 基于http的断点续传和多线程下载

    HTTP协议的GET方法,支持只请求某个资源的某一部分: 206 Partial Content 部分内容响应: Range 请求的资源范围: Content-Range 响应的资源范围: 断点续传: ...

  5. java多线程下载和断点续传

    java多线程下载和断点续传,示例代码只实现了多线程,断点只做了介绍.但是实际测试结果不是很理想,不知道是哪里出了问题.所以贴上来请高手修正. [Java]代码 import java.io.File ...

  6. Java--使用多线程下载,断点续传技术原理(RandomAccessFile)

    一.基础知识 1.什么是线程?什么是进程?它们之间的关系? 可以参考之前的一篇文章:java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器 简 ...

  7. android 多线程下载 断点续传

    来源:网易云课堂Android极客班第八次作业练习 练习内容: 多线程 asyncTask handler 多线程下载的原理 首先获取到目标文件的大小,然后在磁盘上申请一块空间用于保存目标文件,接着把 ...

  8. Android开发之多线程下载、断点续传、进度条和文本显示

    代码实现了在Android环境下的多线程下载.断点续传.进度条显示和文本显示百分数: import java.io.BufferedReader; import java.io.File; impor ...

  9. Java开发之多线程下载和断点续传

    代码实现了多线程下载和断点续传功能 import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream ...

随机推荐

  1. jdbc编程学习之增删改查(2)

    一,enum类型的使用 在SQL中没有布尔类型的数据,我们都使用过布尔类型,当属性的值只用两种情况时.例如性别等.那在数据库对这些属性的值个数比较少时我们应该使用什么数据类型呢?SQL给我们提供了枚举 ...

  2. 配置 nginx 访问资源目录,nginx配置 root 与 alias 的区别

    比如说想要把 /home/source 目录作为资源目录,那么需要如下配置: location /source/ { #识别url路径后,nginx会到/home/文件路径下,去匹配/source r ...

  3. Redis 设计与实现 6:五大数据类型之列表

    列表对象有 3 种编码:ziplist.linkedlist.quicklist. ziplist 和 linkedlist 是 3.2 版本之前的编码. quicklist 是 3.2 版本新增的编 ...

  4. 华为存储18500 V5配置SNMP

    配置流程 配置SNMPV1/V2C 配置端口 admin:/>show snmp port SNMP Listening Port : 161 admin:/>change snmp po ...

  5. 智能BPOS小票模板字体的使用

    关于伯俊智能BPOS零售小票模板的设置,常用字体"黑体"."宋体"."Arial"这几个字体,在设置的时候看似没有问题, 但是在正真使用打印 ...

  6. TurtleBot3 Waffle (tx2版华夫)(5)激活你的雷达

    重要提示:请在配网通信成功后进行操作,配网后再次开机需要重新验证通信: 重要提示:[Remote PC]代表PC端.[TurtelBot]代表树莓派端: 5.1.操作步骤 1)[Remote PC]  ...

  7. Spark Streaming 与Filnk对比分析

    转:https://mp.weixin.qq.com/s/jllAegJMYh_by95FhHt0jA

  8. 风炫安全WEB安全学习第二十四节课 利用XSS钓鱼攻击

    风炫安全WEB安全学习第二十四节课 利用XSS钓鱼攻击 XSS钓鱼攻击 HTTP Basic Authentication认证 大家在登录网站的时候,大部分时候是通过一个表单提交登录信息. 但是有时候 ...

  9. M43 第一阶段考试

    一.解答题 1.统计当前主机的TCP协议网络各种连接状态出现的次数 netstat -an | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a ...

  10. maven 的安装与配置详细步骤

    1. 直接搜索maven 2. 进入后点击download界面,这时出现的是当前最新版本, 当然还有以前的版本可供下载 3. 下载解压到你指定的目录后,需要配置一下环境变量. a. 右键此电脑点击属性 ...