简介
HTTP(超文本传输协议),是用于从万维网服务器传输超文本到本地浏览器的传送协议,是互联网上应用最为广泛的一种网络协议,所有的www文件都必须遵守这个标准。
HTTP是一个属于应用层的面向对象的协议,由于其简便、快速的方式,适用于分布式超媒体信息系统。 它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。
HTTP协议版本
大致的版本可以分为以下五个:
- HTTP/0.9(初始诞生)
- HTTP/1.0
- HTTP/1.1
- HTTP/2
- HTTP/3
发展的历史如下:
HTTP/0.9
该版本极其简单,起初是为了学术交流,传递html文本,只有一个命令 GET
- TCP建立连接
- 客户端发GET请求 /index.html
- 服务器返回html文件,以ASCII字符流返回
- 断开连接
-- 特点:
- 只有请求行,没有请求头和请求体
- 服务器没有响应头,直接返回数据就可以
- 内容都是以ASCII字符流来传输
HTTP/1.0
浏览器的诞生,支持多类型文件的下载 (html, css, js, 图片,音频,视频),于是http就不得不支持不同类型文件的下载
-- 如何实现多种类型文件的下载?
- 引入请求头和响应头,key-value
- http发请求时会带上请求头信息,服务器返回数据时,会先返回响应头信息
-- 请求头和响应头是如何工作的?
- 浏览器要知道服务器返回的类型;
- 浏览器要知道服务器返回的数据压缩方式;
- 浏览器要知道服务器文件的编码方式;
请求头:
js
accept: text/html //类型
accept-encoding: gzip,deflate,br //压缩方式
accept-Charset: ISO-8859-1,utf-8 //编码方式
accept-language: zh-CN,zh-xx //语言
响应头:
js
content-encoding: br
content-type: text/html; charset=utf-8
status: 200 //状态码
cache //(缓存)机制
content-length: 901
HTTP/1.1 (缝缝补补)
对于 1.0:
lua
建立连接 --- HTTP请求 HTTP响应 --- 断开连接
建立连接 --- HTTP请求 HTTP响应 --- 断开连接
建立连接 --- HTTP请求 HTTP响应 --- 断开连接
···
在 1.1 时,引入了持久连接 :建立一个TCP连接,可以进行多个http请求,即:
lua
-- http请求1 http响应1 --
-- http请求2 http响应2 --
建立连接 -- http请求3 http响应3 --断开连接
-- http请求4 http响应4 --
-- http请求5 http响应5 --
···
请求头:Connection: close (不启用持久连接)
目前,对于同一个域名,大多数浏览器允许同时建立6个持久连接
其他功能:
- 管道机制(pipelining),即在同一个TCP连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率。
Content-Length
字段,一个TCP连接现在可以传送多个回应,势必就要有一种机制,区分数据包是属于哪一个回应的。这就是Content-length字段的作用,声明本次回应的数据长度。
yaml
Content-Length: 3495
上面代码告诉浏览器,本次回应的长度是3495个字节,后面的字节就属于下一个回应了。
- 分块传输编码(chunked transfer encoding), 将数据分割成若干个数据块,每个数据块上标记数据块的长度,最后发送一个空数据块来告诉浏览器数据传输完毕。
makefile
Transfer-Encoding: chunked
- 客户端请求的头信息新增了
Host
字段,用来指定服务器的域名。
arduino
Host: www.example.com
//有了Host字段,就可以将请求发往同一台服务器上的不同网站,为虚拟主机的兴起打下了基础
缺点 :队头阻塞
虽然1.1版允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为'队头阻塞'
这里再简单总结一下:
http/1.1的优化:
- 增加了持久化连接
- 浏览器可以同时维护6个TCP连接
- 使用了CDN实现域名分片
主要存在的问题:
-
对带宽的利用率很低
-- TCP慢启动
-- 同时开启多条TCP连接会竞争固定带宽
-- 队头阻塞问题
HTTP/2
多路复用(解决队头阻塞问题)
- 一个域名只使用一个TCP的长连接
- 资源并行请求
二进制协议
HTTP/1.1 版的头信息肯定是文本(ASCII编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为"帧"(frame):头信息帧和数据帧。
二进制协议的一个好处是,可以定义额外的帧。HTTP/2 定义了近十种帧,为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。
可以设置请求的优先级 :优先级越高,服务器就会越早回应
服务器推送 :当服务器给客户端返回一个html后,服务器自己知道该html中需要哪几份js和css,那么服务器就提前准备好这些js和css并且一并将js,css发送给浏览器
头信息压缩压缩 :请求头和响应头
一方面,头信息使用gzip
或compress
压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
2.0的缺陷:
- TCP的队头阻塞:因为TCP的传输是有序的,单个数据包丢失会造成阻塞
- TCP建立连接的延时:TCP握手,HTTPS中的TLS加密过程也有一次握手
HTTP/3
由于HTTP/2存在的缺陷,那我们能否通过改进TCP协议来优化呢?
改进TCP协议(TCP僵化,实现不可能)
- 太多中间设备基于TCP生产,路由器、交换机...
- 操作系统内核也是基于TCP来工作的
于是乎HTTP/2存在的问题都是TCP导致的,既然改进TCP协议不现实,那不妨大胆一点,跳出这个禁锢,我们能否不基于TCP传输,使用UDP进行传输呢?所以有了UDP协议的升级。
QUIC协议(UDP升级)
- 有多路复用
- 传输可靠
HTTP/3面临的挑战
- 浏览器和服务器都要升级支持QUIC协议
- 系统对UDP的优化很低,对TCP的优化很高
- 中间设备僵化
总结
这就是HTTP至今为止的故事,看完本文如果对你有所帮助,记得点赞支持,也可收藏方便随时查看啦,文章可能存在一些错误,欢迎指出,一起讨论共同进步。