HTTP 协议的初印象:
是基于 TCP/IP 协议的应用层协议, 不涉及数据包的传输, 主要规定了客户端和服务器之间的通信格式, 默认使用 80 端口.
1 HTTP 协议 0.9 版(1991 年)
是个弱智协议, 客户端发起请求以后, 服务器只能返回 html 格式的字符串, 不能回应别的格式.
只有一个 GET 命令:
GET /index.HTML
上面命令表示, TCP 连接 (connection) 建立后, 客户端向服务器请求 (request) 网页 index.HTML.
服务器发送完毕, 就关闭 TCP 连接.
2 HTTP 协议 1.0 版(1996 年)
与 0.9 版本相比, 有以下几点变化:
这个版本允许发送的内容变多了, 不仅可以传输文字, 还能传输图像, 视频, 二进制文件.
除了 GET,POST,HEAD 这两个命令都可以用, 浏览器和服务器的互动手段增加了.
HTTP 请求和回应的格式也变了. 每次通信都必须包括头信息, 用来描述一些元数据.
新增的功能还有:
状态码
多字符集支持
多部分发送
权限
缓存
内容编码
2.1 请求形式:
- <!-- 请求命令, 必须在尾部添加协议版本(HTTP/1.0)-->
- GET /HTTP/1.0
- <!-- 多行头信息, 描述了客户端的情况 -->
- User-Agent: Mozilla/5.0(Macintosh: Intel Mac PS X 10_10_5)
- <!-- 客户端表示自己可以接受任何格式的数据 -->
- Accept:*/*
2.2 回应格式
- <!-- 头信息 -->
- HTTP/1.0 200 OK
- Content-Type: text/plain
- Content-Length: 137582
- Expires:Thu, 05 Dec 1997 16:00:00 GMT
- Server: Apache 0.84
- <!-- 数据 -->
- <HTML>
- <body>Hello World</body>
- </HTML>
其中, 头信息的第一行是 "协议的版本 + 状态码(status code) + 状态描述"
2.3 Content-Type 字段
Content-Type 字段的作用是告诉客户端从服务端返回的数据是什么格式.
常见的 ContentType:
- text/plain
- text/HTML
- text/CSS
- image/jpeg
- image/PNG
- image/svg+xml
- audio/mp4
- video/mp4
- application/JavaScript
- application/PDF
- application/zip
- application/atom+xml
数据类型的构成包括一级类型和二级类型, 中间用斜杠隔开. 这些类型都被称为 MIME type.
MIME type 不仅用于 HTTP 请求, 也可以用于别的地方, 比如 HTML 网页.
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <!-- 等同于 -->
- <meta charset="utf-8" />
2.4 数据压缩
客户端在请求的时候, 用 Accept - Encoding 字段说明自己可以接受哪些压缩方法.
Accept-Encoding: gzip, deflate
而服务器使用 Content-Encoding 字段说明数据的压缩方法.
- Content-Encoding: gzip
- Content-Encoding: compress
- Content-Encoding: deflate
2.5 HTTP/1.0 协议的缺点
每个 TCP 连接只能发送一个请求, 数据发送完毕连接就关闭了, 如果要请求别的资源, 必须再新建一个连接.
但是 TCP 连接的成本很高, 因为客户端和服务器的三次握手, 并且启动发送的速率较慢.
有一些浏览器为了解决 TCP 会关闭的问题, 采用了非标准的 Connection 字段.
浏览器请求和服务器回应都带有这个字段:
Connection: keep-alive
这样的话, 一个可以复用的连接建立了, 直到客户端或者服务器主动关闭连接. 但是不同的浏览器实现不同, 这不是一个好的解决办法.
3 HTTP 协议 1.1 版(1997 年)
3.1 持久连接
相比 1.0 版, 1.1 版最大的变化是保持连接, 即默认 TCP 连接不关闭, 可以被多个请求复用, 不用再声明 Connection: keep-alive.
那怎么关闭呢? 如果客户端或者服务器发现对方一段时间内没有活动, 就可以主动关闭连接. 不过最好还是客户端在发送最后一个请求的时候, 发送一个 Connection:close, 明确要求服务器关闭 TCP 连接.
另外, 对于同一个域名, 大多数浏览器允许同时建立 6 个持久连接.
3.2 管道机制
管道机制: 在同一个 TCP 连接里, 客户端可以同时发送多个请求.
以前的做法是客户端先发送 A 请求, 然后再发送 B 请求. 管道机制是允许浏览器同时发送 A 请求和 B 请求, 但是服务器还是按照顺序进行的, 先回应 A 请求再回应 B 请求.
3.3 区分数据包
一个 TCP 连接现在可以传送多个回应, 势必就要有一种机制, 区分数据包是属于哪一个回应的.
Content-length 字段的作用, 声明本次回应的数据长度.
Content-Length: 3495
上面的字段告诉客户端, 本次回应的长度是 3495 个字节, 后面的字节就属于下一个回应了.
所以, 使用 Content-Length 字段的前提条件是, 服务器发送回应之前, 必须知道回应的数据长度.
而在 1.0 版本中, 这个字段可以存在, 也可以不存在, 因为服务端关闭了 TCP 连接说明数据包已经全了.
3.4 其他功能
1.1 版新增了很多动词方法: PUT,PATCH,HEAD,OPTIONS,DELETE.
客户端的请求头信息增加了 Host 字段, 用来指定服务器的域名.
这个字段可以将请求发往同一台服务器的不同网站.
如:
Host: www.example.com
3.5 缺点
"队头堵塞": 在 1.1 版协议中, 虽然可以在一个 TCP 中发送多个请求, 服务器只有处理完一个回应, 才会进行下一个回应. 要是前面的回应特别慢, 后面就会有许多请求排队等着.
为了避免这个问题, 只有两种方法: 一是减少请求数, 二是同时多开持久连接.
所以产生了很多网页优化技巧, 比如合并脚本和样式表, 将图片嵌入 CSS 代码, 域名分片等, 但是 HTTP 协议设计得更好的话, 这些工作完全没有必要做的.
4 SPDY 协议 (2009 年)
2009 年, 谷歌公开了自己搞的 SPDY 协议, 主要为了解决 HTTP/1.1 效率不高的问题.
这个协议最终被当作了 HTTP/2 的基础.
5 HTTP 协议 2 版
HTTP/2 协议不叫 HTTP/2.0, 这是因为标准委员会不在打算发布子版本, 下一个新的版本将会是 HTTP/3.
5.1 二进制协议
HTTP 协议的头肯定是文本(ASCII 码), 数据体可以是文本, 也可以是二进制.
但 HTTP/2 协议头和数据体都是二进制, 是一个彻彻底底的二进制协议.
这里的头和数据体都换了一个身份叫做 "帧": 头信息帧和数据帧.
二进制协议的好处就是可以定义额外的帧, HTTP/2 有近十种帧, 为将来的高级应用打好了基础, 因为二进制解析比文本解析更方便.
5.2 多工
HTTP/2 协议复用 TCP 连接, 也就是说客户端和服务端可以同时发送或者回应多个请求.
比如说, 在一个 TCP 里, 客户端给服务端发送了 A 和 B 两个请求, 按道理说应该先处理 A 请求, 但是服务端发现 A 请求有点费劲儿, 就先把 A 请求中处理好的发出去, 接着回应 B 请求, 完事儿以后再发送 A 请求中剩下的部分.
像这样双向, 实时的通信, 就叫做多工(Multiplexing).
5.3 数据流
HTTP/2 的数据包不是按照顺序发送的, 同一个连接里的数据包可能属于多个请求. 所以需要一个编号, 这个编号指明数据包属于哪一个请求或者回应.
这里有一个概念叫做数据流, 我们把一个请求或者回应的所有数据包合在一起称为一个数据流. 每个数据流都有一个独一无二的编号, 数据包发送的时候都必须标定数据流编号.
客户端请求的数据流编号一律为基数, 而服务端回应的数据流编号为偶数.
在 HTTP/1.1 中终止请求的方式只能是关闭 TCP 连接, 而现在可以发送一个信号:(RST_STREAM 帧), 取消这个数据流.
也就是说 HTTP/2 可以取消某一次请求, 同时能保证 TCP 连接打开, 可以被其他请求所使用.
此外, 客户端可以指定数据流的优先级, 优先级高的服务器越早响应.
5.4 头信息压缩
因为协议不带有状态, 每次请求都必须附上所有信息. 有一些信息是重复的, 这样会影响数据传输速度, 浪费带宽.
HTTP/2 采用头信息压缩机制可以减少不利影响. 首先是将信息压缩后再发送(gzip 或者 compress), 其次是客户端 和服务器同时维护一张头信息表, 这个表很神奇的地方在于可以利用索引进行管理, 只要我们发送索引就可以表示我们传输的信息, 这样就能够提高速度.
5.5 主动推送
HTTP/2 允许服务器在没有经过允许的情况下, 可以主动向客户端推送资源 . 这个过程叫做服务器推送(server push).
举一个例子, 别发送邮件给我们的时候, 邮箱会冒个弹框出来告诉我们有人往邮箱里投递了一封邮件. 注意, 此时我们并没有刷新网页.
服务器推送还可能用到消息提醒, 静态资源自动推送到服务端等场景.
来源: https://www.cnblogs.com/kurryluo/p/10975949.html