文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

http协议之Range

2023-09-02 17:33

关注

http协议中可能会遇到:请求取消或数据传输中断,这时客户端已经收到了部分数据,后面再请求时最好能请求剩余部分(断点续传);或者,对于某个较大的文件,能够支持客户端多线程分片下载...

以上在我们平时应用中已经有很多产品支持了,其中原理就和http协议中的Range有关。

Range是在 HTTP/1.1里新增的一个请求头字段域,rfc文档:RFC 7233: Hypertext Transfer Protocol (HTTP/1.1): Range Requests HTTP协议博大精深,设计有很多巧妙的地方,Range也许就是一处吧。

1、Range协议:

1)检查服务端是否支持Range:

客户端发起请求,服务端收到后在response的header中如果有Accept-Ranges:bytes ,表示支持Range。

比如,我们通过curl -I发起一个请求,查看响应头信息:(curl -I 表示Show document info only)

$ curl -I http://127.0.0.1/rt1/2.mp4HTTP/1.1 200 OKServer: openresty/1.19.9.1Date: Thu, 12 Jan 2023 08:04:32 GMTContent-Type: video/mp4Content-Length: 505199705Last-Modified: Fri, 08 Jul 2022 07:09:25 GMTConnection: keep-aliveETag: "62c7d825-1e1cbc59"Accept-Ranges: bytes

上面Accept-Ranges: bytes 表示界定范围的单位是 bytes;Content-Length 表示文件大小。如果服务端响应header内容Accept-Ranges:none 表示不支持!

2)Range协议格式:

客户端在header中添加Range信息,表示发起一次范围请求,格式如下:

Range:unit=first byte pos-[last byte pos]

例如: 单位(如bytes)= 开始字节位置-结束字节位置。

服务端响应在header中添加Range信息:

Content-Range: unit first byte pos-[last byte pos]/[entity length]
例如:Content-Range:字节 开始字节位置-结束字节位置/文件大小。

注:first byte pos从0开始!
看个例子:假设有个文件大小为 5000 个 byte,现要开启多线程下载(比如4个),每个线程负责下载一个部分,那么我们可以划分为:

Range: bytes=0-1199 头1200个字节Range: bytes=1200-2399 第二个1200字节Range: bytes=2400-3599 第三个1200字节Range: bytes=3600-5000 最后的1400字节服务器给出响应:// 第1个响应Content-Length:1200Content-Range:bytes 0-1199/5000// 第2个响应Content-Length:1200Content-Range:bytes 1200-2399/5000// 第3个响应Content-Length:1200Content-Range:bytes 2400-3599/5000// 第4个响应Content-Length:1400Content-Range:bytes 3600-5000/5000

Content-Length表示对应范围的大小,Content-Range返回和请求对应的范围。

3)Range请求的响应码:

Server通过请求头中的Range: bytes=0-xxx来判断是否是做 Range 请求,如果这个值存在而且有效,则只发回请求的那部分文件内容,响应的状态码变成206,表示Partial Content,并设置Content-Range。如果无效,则返回416状态码,表明Request Range Not Satisfiable。如果请求头中不带 Range,那么 Server则正常响应,也不会设置 Content-Range 等。

4)与分块传输编码的对比

Transfer-Encoding 首部允许分块编码,这在数据量很大,并且在请求未能完全处理完成之前无法知晓响应的体积大小的情况下非常有用。服务器会直接把数据发送给客户端而无需进行缓冲或确定响应的精确大小——后者会增加延迟。范围请求与分块传输是兼容的,可以单独或搭配使用。

2、从服务端请求特定范围的数据

1)单一范围:

客户端请求时,可以在header中通过Range表示请求的范围,这时如果服务端支持Range,则会返回206状态码,并返回指定范围的数据,并在header中添加Content-Range;否则不支持,则返回200。

例如:(curl -i 表示打印响应头)

$ curl -i -H "Range: bytes=0-102300"   http://127.0.0.1/f1.txtHTTP/1.1 206 Partial ContentServer: openresty/1.19.9.1Date: Thu, 12 Jan 2023 09:34:49 GMTContent-Type: text/plainContent-Length: 10Last-Modified: Thu, 12 Jan 2023 09:34:44 GMTConnection: keep-aliveETag: "63bfd434-a"Content-Range: bytes 0-9/10123456789

2)多范围:

$ curl -i -H "Range: bytes=0-1,4-5"   http://127.0.0.1/f1.txtHTTP/1.1 206 Partial ContentServer: openresty/1.19.9.1Date: Thu, 12 Jan 2023 09:36:21 GMTContent-Type: multipart/byteranges; boundary=00000000000000000001Content-Length: 198Last-Modified: Thu, 12 Jan 2023 09:34:44 GMTConnection: keep-aliveETag: "63bfd434-a"--00000000000000000001Content-Type: text/plainContent-Range: bytes 0-1/1012--00000000000000000001Content-Type: text/plainContent-Range: bytes 4-5/1056--00000000000000000001--

Range 头部也支持一次请求文档的多个部分。请求范围用一个逗号分隔开。

服务器返回 206 Partial Content 状态码和 Content-Type:multipart/byteranges; boundary=00000000000000000001 头部,Content-Type:multipart/byteranges 表示这个响应有多个 byterange。每一部分 byterange 都有他自己的 Content-type 头部和 Content-Range,并且使用 boundary 参数对 body 进行划分。

3)条件范围:

当(中断之后)重新开始请求更多资源片段的时候,必须确保自从上一个片段被接收之后该资源没有进行过修改。

The If-Range 请求首部可以用来生成条件式范围请求:假如条件满足的话,条件请求就会生效,服务器会返回状态码为 206 Partial 的响应,以及相应的消息主体。假如条件未能得到满足,那么就会返回状态码为 200 OK 的响应,同时返回整个资源。该首部可以与 Last-Modified 验证器或者 ETag 一起使用,但是二者不能同时使用。

参考:

HTTP 请求范围 - HTTP | MDN

聊一聊HTTP的Range, Content-Range | HappyCoding:)

3、示例:nginx提供视频下载服务

http的Range可以提供范围请求,最重要的应用就是视频播放。

1)nginx配置:

使用openresty的docker景象启动,配置如下

server {    listen       80;    server_name  localhost;    location = /f1.txt {        root /data/;    }    location = /rt1/2.mp4 {        root /data/;    }

创建如下文件:/data/rt1/2.mp4 /data/f1.txt

说明:nginx本身支持了Range,我看nginx也提供了ngx_http_slice_module模块(--with-http_slice_module参数),支持Range回源。

2)浏览器访问:

配置好nginx后,通过浏览器访问:http://127.0.0.1/rt1/2.mp4 打开chrome的控制面板,切换到network tab页

可以看到有多个请求,第一个请求的状态码是200,剩余请求的状态码都是206(partial content-部分内容)。而且chrome非常贴心地用内置的视频解码工具来播放MP4文件,还有暂停按钮。(如果开始播放后不暂停,nginx会不断地给chrome吐数据,这个过程不会中断,暂停按钮会中断此次通信,断开connection,此时nginx才会写入access log)。

参考:【nginx】大文件下载 - awildfish - 博客园

来源地址:https://blog.csdn.net/liuxiao723846/article/details/128665109

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-服务器
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯