【网络通信 -- 直播】IM 学习系列 -- 网络通信协议简介(HTTP 协议 三)

【网络通信 -- 直播】IM 学习系列 -- 网络通信协议简介(HTTP 协议 三)

【1】HTTP 的实体数据

【1.1】数据类型与编码

MIME,多用途互联网邮件扩展(Multipurpose Internet Mail Extensions), MIME 把数据分成了八大类,每个大类下再细分出多个子类,形式是“type/subtype”的字符串;
HTTP 中常用的类别:
text,即文本格式的可读数据,如 超文本文档 text/html、纯文本 text/plain、样式表 text/css 等;
image,即图像文件,如 image/gif、image/jpeg、image/png 等;
audio/video,音频和视频数据,例如 audio/mpeg、video/mp4 等;
application,数据格式不固定,可能是文本也可能是二进制,必须由上层应用程序来解释;如 application/json、application/javascript、application/pdf 等; application/octet-stream,即不透明的二进制数据,表示无法确定数据类型;

Encoding type(编码格式) 常用类型
gzip,GNU zip 压缩格式,deflate,zlib(deflate)压缩格式;br,专门为 HTTP 优化的新压缩算法(Brotli)

【1.2】数据类型使用的头字段

HTTP 协议为此定义了两个 Accept 请求头字段和两个 Content 实体头字段,用于客户端和服务器进行“内容协商”,客户端用 Accept 头告诉服务器希望接收什么样的数据,服务器用 Content 头告诉客户端实际发送了什么样的数据;

Accept 字段标记的是客户端可理解的 MIME type,可以用“,”做分隔符列出多个类型
Accept: text/html,application/xml,image/webp,image/png

Content-Type 告诉实体数据的真实类型
Content-Type: text/html
Content-Type: image/png

Accept-Encoding 字段标记的是客户端支持的压缩格式可以用“,”列出多个,服务器可以选择其中一种来压缩数据;
Content-Encoding 实际使用的压缩格式;
Accept-Encoding: gzip, deflate, br
Content-Encoding: gzip

【1.3】语言类型

语言类型即自然语言,例如英语、汉语、日语等,用“type-subtype”的形式标记语言与下属的地区性方言

语言类型使用的头字段
Accept-Language 字段标记了客户端可理解的自然语言,也允许用“,”做分隔符列出多个类型
Accept-Language: zh-CN, zh, en

Content-Language 告诉客户端实体数据使用的实际语言类型
Content-Language: zh-CN

请求头字段是 Accept-Charset表示字符集,Content-Type 字段的数据类型后面用“charset=xxx”来表示字符集
Accept-Charset: gbk, utf-8
Content-Type: text/html; charset=utf-8

【1.4】内容协商的质量值
HTTP 协议里用 Accept、Accept-Encoding、Accept-Language 等请求头字段进行内容协商的时候,可以用一种特殊的“q”参数表示权重来设定优先级,权重的最大值是 1,最小值是 0.01,默认值是 1,如果值是 0 就表示拒绝;具体的形式是在数据类型或语言代码后面加一个“;”,然后是“q=value”,在 HTTP 的内容协商里“;”的意义是小于“,”的;

Accept: text/html,application/xml;q=0.9,*/*;q=0.8
表示浏览器最希望使用的是 HTML 文件,权重是 1,其次是 XML 文件,权重是 0.9,最后是任意数据类型,权重是 0.8;
服务器收到请求头后,就会计算权重,再根据自己的实际情况优先输出 HTML 或者 XML;

【2】HTTP 传输大文件的方法

【2.1】数据压缩

缺点 : gzip 等压缩算法通常只对文本文件有较好的压缩率,而图片、音频视频等多媒体数据本身就已经是高度压缩的,再用 gzip 处理也不会变小(甚至还有可能会增大一点);

【2.2】分块传输

分块传输在 HTTP 协议里就是“chunked”分块传输编码,在响应报文里用头字段“Transfer-Encoding: chunked”来表示,意思是报文里的 body 部分不是一次性发过来的,而是分成了许多的块(chunk)逐个发送
“Transfer-Encoding: chunked”和“Content-Length”这两个字段是互斥的,即响应报文里这两个字段不能同时出现,一个响应报文的传输要么是长度已知,要么是长度未知(chunked)

分块传输的编码规则类似于响应头采用了明文的方式,
1. 每个分块包含两个部分,长度头和数据块;
2. 长度头是以 CRLF(回车换行,即\r\n)结尾的一行明文,用 16 进制数字表示长度;
3. 数据块紧跟在长度头后,最后也用 CRLF 结尾,但数据不包含 CRLF;
4. 最后用一个长度为 0 的块表示结束,即“0\r\n\r\n”;

【2.3】范围请求

“范围请求”(range requests)允许客户端在请求头里使用专用字段来表示只获取文件的一部分,相当于是客户端的“化整为零”,
范围请求不是 Web 服务器必备的功能,服务器若支持范围请求则在响应头里使用字段“Accept-Ranges: bytes”告知客户端支;若服务器不支持范围请求则发送“Accept-Ranges: none”,或者干脆不发送“Accept-Ranges”字段;


请求头 Range 是 HTTP 范围请求的专用字段,格式是“bytes=x-y”,其中的 x 和 y 是以字节为单位的数据范围,要注意 x、y 表示的是“偏移量”,范围必须从 0 计数,例如前 10 个字节表示为“0-9”,第二个 10 字节表示为“10-19”,而“0-10”实际上是前 11 个字节;range 的格式也很灵活,起点 x 和终点 y 可以省略,能够很方便地表示正数或者倒数的范围;
假设文件是 100 个字节则:“0-”表示从文档起点到文档终点,相当于“0-99”,即整个文件;“10-”是从第 10 个字节开始到文档末尾,相当于“10-99”;“-1”是文档的最后一个字节,相当于“99-99”;“-10”是从文档末尾倒数 10 个字节,相当于“90-99”;

服务器收到 Range 字段后,需要做四件事;
第一,必须检查范围是否合法,比如文件只有 100 个字节,但请求“200-300”,这就是范围越界了,服务器就会返回状态码 416,意思是“范围请求有误,无法处理”;
第二,如果范围正确,服务器就可以根据 Range 头计算偏移量,读取文件的片段了,返回状态码 “206 Partial Content” 和 200 的意思差不多,但表示 body 只是原数据的一部分;
第三,服务器要添加一个响应头字段 Content-Range,告诉片段的实际偏移量和资源的总大小,格式是“bytes x-y/length”,与 Range 头区别在没有“=”,范围后多了总长度,例如,对于“0-10”的范围请求,值就是“bytes 0-10/100”;
第四,发送数据,直接把片段用 TCP 发给客户端,一个范围请求便处理完了;

多段下载、断点续传也是基于范围请求实现的,要点是:
1. 先发个 HEAD,看服务器是否支持范围请求,同时获取文件的大小;
2. 开 N 个线程,每个线程使用 Range 字段划分出各自负责下载的片段,发请求传输数据;
3. 下载意外中断也不怕,不必重头再来一遍,只要根据上次的下载记录,用 Range 请求剩下的部分;

【2.4】多段数据

这种情况需要使用一种特殊的 MIME 类型:“multipart/byteranges”,表示报文的 body 是由多段字节序列组成的,并且还要用一个参数“boundary=xxx”给出段之间的分隔标记;

每一个分段必须以“- -boundary”开始(前面加两个“-”),之后要用“Content-Type”和“Content-Range”标记这段数据的类型和所在范围,然后就像普通的响应头一样以回车换行结束,再加上分段数据,最后用一个“- -boundary- -”(前后各有两个“-”)表示所有的分段结束;

问题举例

【1】假设你要使用 POST 方法向服务器提交一些 JSON 格式的数据,里面包含有中文,请求头应该是什么样子的呢

POST /serv/v1/user/auth HTTP/1.1
Content-Type: application/json; charset=gbk, utf-8
Content-Language: zh-CN, zh

【2】如果对一个被 gzip 的文件执行范围请求,比如“Range: bytes=10-19”,那么这个范围是应用于原文件还是压缩后的文件呢

range 是针对原文件的;

参考致谢
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。

【1】透视HTTP协议

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章