HTTP 协议详解:连接方式、版本演进与报文首部
HTTP 协议简介
HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。 客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应, 响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。HTTP是不保存状态的协议,既无状态协议,协议本身对于请求或响应之间的通信状态不进行保存,因此连接双方不能知晓对方当前的身份和状态。 这也是Cookie技术产生的重要原因之一:客户端的状态管理。浏览器会根据从服务器端发送的响应报文内Set-Cookie首部字段信息自动保持Cookie。 而每次客户端发送HTTP请求,都会在请求报文中携带Cookie,作为服务端识别客户端身份状态的标识。
串行连接、持久连接、管道化持久连接、http/2.0 多路复用简介
串行连接
HTTP 有无连接的特性,即每次连接只能处理一个请求,收到响应后立即断开连接。 HTTP/1.0 版本(称为串行连接或短连接、短轮询)中每次 HTTP 通信后都要断开 TCP 连接, 所以每个新的 HTTP 请求都需要建立一个新的连接。但在现在网站动则几十条 HTTP 请求的情况下,很容易达到浏览器请求上限, 并且每次请求都建立新的 tcp 连接(每次都有三次握手四次挥别)极大的增加了通信开销。
持久连接(长连接)
一定时间内,同一域名下的 HTTP 请求,只要两端都没有提出断开连接,则持久保持 TCP 连接状态,其他请求可以复用这个连接通道。 HTTP/1.1 实现并默认了所有连接都是持久连接,这样客户端发起多个 HTTP 请求时就减少了 TCP 握手造成的网络资源和通信时间的浪费。 但是持久连接采用阻塞模式,下次请求必须等到上次响应返回后才能发起,如果上次的请求还没返回响应内容,下次请求就只能等着(就是常说的线头阻塞)
管道化持久连接
管道化持久连接可以不用等待响应返回而发送下个请求并按顺序返回响应,现代浏览器并未默认开启管道化
HTTP/2.0 多路复用
每个 HTTP 请求都有一个序列标识符,这样浏览器可以并发多个请求,服务器接收到数据后,再根据序列标识符重新排序成不同的请求报文,而不会导致数据错乱。 同样,服务端也可以并发返回多个响应给浏览器,浏览器收到后根据序列标识重新排序并归入各自的请求的响应报文。并且同一个域名下的所有请求都复用同一个 TCP 连接,极大增加了服务器处理并发的上限。
WebSocket
WebSocket 是 HTML5 提出的一种客户端和服务端通讯的全双工协议,由客户端发起请求,建立连接之后不仅客户端可以主动向服务端发送请求,服务端可以主动向客户端推送信息。
URI
HTTP 协议使用 URI 定位互联网上的资源。概念:
URI(Universal Resource Identifier:统一资源标识符):在某个规则下能把这个资源独一无二标示出来(如同人的身份证一样)URL(Universal Resource Locator:统一资源定位符):使用浏览器访问WEB页面时需要输入的网页地址URN(Universal Resource Name:统一资源名称)。
HTTP 版本
HTTP/1.0
每次请求都打开一个新的 TCP 链接,收到响应之后立即断开连接。
HTTP/1.1
- 引入了更多的缓存控制策略,如
Entity tag,If-Unmodified-Since,If-Match,If-None-Match等 - 允许范围请求,即在请求头中加入
Range头部 - 请求消息和响应消息都必须包含
Host头部,以区分同一个物理主机中的不同虚拟主机的域名 - 默认开启持久连接,在一个
TCP连接上可以传送多个HTTP请求和响应,采用管线化的方式(每个域名最多维护6个TCP持久链接)解决队头阻塞问题,减少了建立和关闭连接的消耗和延迟。
HTTP/2.0
- 新的二进制格式:
HTTP/1.x的解析是基于文本的。基于文本协议的解析存在天然缺陷,文本的表现形式有多样性,要做到全面性考虑的场景必然很多。二进制则不同,只识别0和1的组合。基于这种考虑HTTP/2.0的协议解析采用二进制格式,方便且强大。 - 多路复用:
HTTP/2.0支持多路复用,这是HTTP/1.1持久连接的升级版。多路复用,就是在一个TCP连接中可以存在多条流,也就是可以发送多个请求,服务端则可以通过帧中的标识知道该帧属于哪个流(即请求),通过重新排序还原请求。多路复用允许并发的发起多个请求,每个请求及该请求的响应不需要等待其他的请求或响应,避免了线头阻塞问题。这样某个请求任务耗时严重,不会影响到其它连接的正常执行,极大的提高传输性能。 - 头部压缩:
HTTP/1.x的请求和响应头部带有大量信息,而且每次请求都要重复发送,HTTP/2.0使用encoder来减少需要传输的头部大小,通讯双方各自cache一份头部fields表,既避免了重复头部的传输,又减小了需要传输的大小。 - 服务端推送:这里的服务端推送指把客户端所需要的
css/js/img资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤(从缓存中取)。
HTTP/3.0
HTTP/2.0 使用了多路复用,一般来说同一域名下只需要使用一个 TCP 连接。但当这个连接中出现了丢包的情况,那就会导致整个 TCP 都要开始等待重传,也就导致了后面的所有数据都被阻塞了。 Google 基于 UDP 协议推出了一个的 QUIC 协议,并且使用在了 HTTP/3 上
- 避免包阻塞: 多个流的数据包在
TCP连接上传输时,若一个流中的数据包传输出现问题,TCP需要等待该包重传后,才能继续传输其它流的数据包。但在基于UDP的QUIC协议中,不同的流之间的数据传输真正实现了相互独立互不干扰,某个流的数据包在出问题需要重传时,并不会对其他流的数据包传输产生影响。 - 快速重启会话: 普通基于
tcp的连接,是基于两端的ip和端口和协议来建立的。在网络切换场景,例如手机端切换了无线网,使用4G网络,会改变本身的ip,这就导致tcp连接必须重新创建。而QUIC协议使用特有的UUID来标记每一次连接,在网络环境发生变化的时候,只要UUID不变,就能不需要握手,继续传输数据。
HTTP 报文
通用首部字段
下面是请求首部和响应首部中通用的字段名称和作用
| 通用首部 | 作用 |
|---|---|
Cache-Control | 控制缓存的行为:no-cache(强制向服务器再次验证)、no-store(不做任何缓存)、max-age=111111(资源可缓存最大时间 秒)、public(客户端、代理服务器都可利用缓存)、private(代理服务器不可用缓存) |
Connection | 浏览器想要优先使用的连接类型: keep-alive, close(开启和关闭持久连接) |
Date | 创建报文时间 |
Pragma | 只用于请求报文,客户端要求中间服务器不返回缓存的资源 |
Via | 代理服务器相关信息,每经过一个代理服务器就会添加相关信息,用逗号分割 |
Transfer-Encoding | 传输编码方式:chunked 分块传输 |
Upgrade | 要求客户端使用的升级协议,需配合 Connection: Upgrade 一起使用:websocket |
Warning | 缓存相关问题的警告 |
请求首部
| 请求首部 | 作用(请求报文专用) |
|---|---|
Accept | 能正确接收的媒体类型:application/json text/plain |
Accept-Charset | 能正确接收的字符集: unicode-1-1 |
Accept-Encoding | 能正确接收的编码格式列表:gzip deflate |
Accept-Language | 能正确接收的语言列表:zh-cn,zh;1=0.9,en,1=0.8 |
Authorization | 客户端认证信息:Bearer dSdSdFFlsfdjasd123,一般存 token 用 |
Cookie | 发送给服务器的 Cookie 信息 |
Expect | 期待服务端的指定行为 |
From | 请求方邮箱地址 |
Host | 服务器的域名,用于区分单台服务器多个域名的虚拟主机,是 HTTP/1.1 唯一必须包含的字段。 |
If-Match | 两端资源标记比较,只有判断条件为真服务端才会接受请求:If-Mach: 123456,和服务端文件标记比较 |
If-Modified-Since | 本地资源未修改返回 304(比较时间) |
If-None-Match | 本地资源未修改返回 304(比较标记) |
User-Agent | 客户端信息 |
Max-Forwards | 限制可被代理及网关转发的次数 |
Proxy-Authorization | 向代理服务器发送验证信息 |
Range | 请求某个内容的一部分,配合 If-Range 使用 |
Referer | 请求发起页面的原始 URI |
TE | 传输编码方式 |
响应首部
| 响应首部 | 作用(响应报文专用) |
|---|---|
Accept-Ranges | 告知客户端服务器是否可接受范围请求,是 bytes,否 none |
Age | 资源在代理缓存中存在的时间 |
ETag | 资源标识,资源发生变化时标识也会发生改变 |
Location | 客户端重定向到某个 URL |
Proxy-Authenticate | 向代理服务器发送验证信息 |
Server | 服务器名字:Apache Nginx |
WWW-Authenticate | 获取资源需要的认证方案 |
Set-Cookie | 需要存在客户端的信息,一般用于识别用户身份 |
实体首部
| 实体首部 | 作用(补充请求报文或响应报文相关信息) |
|---|---|
Allow | 资源的正确请求方式:GET HEAD POST |
Content-Encoding | 内容的编码格式:gzip deflate |
Content-Language | 内容使用的语言:zh-CN |
Content-Length | request body 长度(即实体主体的大小): |
Content-Location | 返回数据的备用地址 |
Content-MD5 | Base64 加密格式的内容 MD5 检验值 |
Content-Range | 响应主体的内容范围 |
Content-Type | 内容的媒体类型(如 application/json;charset=UTF-8 则会发送预检请求) |
Expires | 内容的过期时间 |
Last_modified | 内容的最后修改时 |
Http 协议与 tcp 通信步骤
如想要浏览 [https://www.baidu.com]
- 客户端向
DNS服务器发出请求,获取 [https://www.baidu.com] 的ip地址 Http协议生成http的请求报文,到达传输层tcp协议为了方便通信,将http发来的请求报文分割成报文段,然后由服务端接受此报文段- 其中上面这一步,
IP协议会搜索对方的地址,一边中转一边传送 - 服务端按序号以原来的顺序重组请求报文
http协议对web服务器的请求内容进行处理,判定需要拿哪些资源- 最后拿到请求的资源再利用
TCP/IP通信协议向客户端进行回传

还没有留言,来发表第一条吧~