网络协议-HTTP 协议

HTTP 协议

HTTP 协议是TCP/IP 网络协议中的应用层协议。

URL - 统一资源定位符

DNS 的作用 将域名 转为 IP 地址

在发送HTTP 协议之前要建立TCP 连接,HTTP 是建立在TCP 连接之上的

HTTP 1.1 版本默认开启Keep-alive,建立一次TCP 连接,可以重复使用

 

HTTP 请求的构建

建立TCP 连接后需要构建HTTP 报文,其报文大概分为三个部分

  • 第一部分:请求行

  • 第二部分:首部

  • 第三部分:正文实体

  

第一部分:请求行

方法有几种类型:

  • Get,获取资源,通常是一个网页,也可能是一个JSON 字符串。

  • Post,主动告诉服务器一些信息,这些信息放到实体中,正文的格式通常是JSON。

  • Put,向指定的资源位置上传新内容, 但HTTP 的服务器通常不允许上传文件,所以在实际应用中,Post通常用来创建一个资源,Put 用来修改一个资源。

  • Delete,用来删除资源的。

 

第二部分:首部字段

首部是key value,通过冒号分隔。通常保存重要字段。

例如,Accept-Charest,表示客户端可以接受的字符集。

例如,Content-Type 指出正文的格式,如果我们进行Post的请求,如果正文是JSON,,那么这个值就是JSON。

缓存的使用,缓存网页中静态的部分,例如图片等。这样可以在更新数据时不必每次都刷新整个页面。

这个架构图如下所示:

  

HTTP头里的 Cache-control 是用来控制缓存的。客户端发送的请求中有max-age 指令时,要判断资源的缓存时间是否比指定的时间小,如果大于指定时间客户端就要重新下载了。

If-Modified-Since 也是关于缓存的。如果服务器的资源更新了,客户端就应该下载最新的资源。

 

HTTP 的报文构建好之后,浏览器如何把它交给下一层,传输层。本质上也是用Socket,只不过这些在浏览器中做好了。

 

HTTP 请求的发送

1、TCP 层会将 源地址和目标地址 信息放到IP 头里,并把它和报文一起交给IP 层传输。

2、IP 层要查看目标IP地址和源IP地址在不在同一个网段

  • 如果在发送ARP 协议获取,目标IP地址的MAC 地址,让后将源MAC 地址和目标MAC 地址放到MAC头中,发送即可。

  • 如果不在同一网段,还是要发送ARP 协议获取网关的MAC 地址,将网关的MAC 和 源MAC 地址放到MAC 头中,发送出去。

3、网关收到包后查看目标IP地址,根据路由协议找下一个路由器,获取下一个路由器的MAC,然后将包发给它。

4、路由器这样一跳一跳的最终到达目标局域网。最后一跳的路由器发现目标IP 就在自己的某一个出口的局域网上。于是在这个局域网上发送ARP 协议,获取目标IP 的MAC 地址,将包发走。

5、目标机器发现MAC 地址符合,将这个包接收,查看IP地址也符合,再查看TCP 的头中的序列号,如果这个包是自己未接收的,就放入接收缓存中,然后回复ACK。

6、TCP 头里还有端口号,指明是哪个应用需要接收的包,这个应用就是HTTP 服务器。服务器查看HTTP 层的消息,是get就返回一个网页,是Post 就创建一个新资源。

 

HTTP 返回的构建

下面这张图是HTTP1.1 版本的返回报文。

返回报文也是分为三个部分:状态行、首部、实体。

1、状态行中有,HTTP 版本;状态码就是202,404这些。短语会说一下出错原因。

2、首部还是 key value。这里面,Retry-After表示客户端在多长时间再尝试一下。Content-Type表示,返回的是HTML 还是JSON。

3、构造好HTTP 报文后,还是有socket发送出,先交给TCP层,TCP层会将HTTP报文分为一个个小段(因为这是一个网页,一个包发不了),然后是IP层,把刚才的过程反向走一遍。

 

HTTP 2.0

HTTP 1.1 的弊端:

  • 在应用层以纯文本的形式通信。

  • 每次通信都要带完整的HTTP头。

  • 不考虑pipeline 模式的话,每次的过程都是一去一回。实时性、并发性存在问题。

HTTP 2.0 解决了 HTTP1.1 的不足:

  • 对HTTP 的头进行压缩,在客户端和服务端建立key value 表,对相同的头只传输表的索引。

  • 将一个TCP 的连接分为多个流,每个流有自己的ID,和双向通道,有优先级。

  • 将传输消息分为更小的消息和帧,并对它们采用二进制传输。让这些消息和帧在多个流中同时传输。这些帧发送时不按顺序,在接收端重新组装。

    Header 帧用于传输Header 内容,并开启一个新的流;Data 帧用于传输正文实体,多个data 帧属于同一个流。

 

假设我们的页面要发送三个独立的请求,一个获取css,一个获取js,一个获取图片jpg。如果使用HTTP1.1 就是串行。但如果是HTTP2.0,就可以在一个连接里并行。如下图所示:

  

HTTP2.0 将三个请求变成三个流,将数据分帧,乱序发送到一个TCP 连接中。

img

 

HTTP 2.0 解决了HTTP1.1 队首阻塞问题。HTTP1.1 要想做到多通道并行,需要通过pipeline 机制建立多条TCP 连接来实现。

 

QUIC 协议

HTTP2.0 也是基于TCP 协议实现的,TCP 协议是有顺序的。虽然HTTP2.0 是多个stream 传输,每个流之间的数据并无关联,流与流之间不需要顺序。

这就像一条大河中航行多个船队,每个船队可以有自己的顺序,但是在入港口的时候却要求和本船队不相干的船只排好顺序再进港一样。

于是Google 将TCP 切换到UDP,构建了一个QUIC 协议。

 

机制一:自定义连接机制

TCP 重连机制太麻烦,还要三次握手啥的。要求的条件也高,既要有IP,还要有端口,差一点就断开重连。因为它保证可靠嘛。在移动互联网情况下,手机的信号或WIFI 不稳定时,都会导致重连。

基于UDP后,可以在QUIC 自己的逻辑里维护连接机制,不再以IP/Port 作为标识,而是以一个64 位的随机数作为ID 标识,而且UDP 是无连接的,当 IP或Port 变化时,只要ID 不变,就不需要重新连接。

 

机制二:自定义重传机制

TCP 有序号和应答机制来保证不丢包,一个序号的包发出去没在一定的时间得到应答就会重发。UDP 并没有这个机制,QUIC 自己构建了一个机制保证不丢包。

QUIC 也有序列号,是递增的。它也有ACK ,也有重传算法。QUIC 定义了一个offset 概念。QUIC 是面向连接的,是一个数据流,发送的数据在这个流里有个偏移量 offset,可以通过offset 查看数据发送到哪了,这样只要这个offset 的包没有来,就要重发。

img

机制三:无阻塞的多路复用

同HTTP2.0 一样,同一条QUIC 连接上可以创建多个 stream,来发送多个HTTP 请求。但QUIC 是基于UDP,一个连接上的多个stream之间没有依赖。

 

机制四:自定义流量控制

TCP 的流量控制是通过滑动窗口协议实现。QUIC 也是通过window_update 控制流量的。但是QUIC 的窗口是适应多路复用机制的。不但在一个连接上有控制窗口,而且在每个stream 上也有控制窗口。

QUIC 的ACK 是基于 offset 的,每个offset 的包来了,并进入缓存,就可以应答,应答后就不会重发,中间的空挡会等待到来或者重发即可,而窗口的起始位置为当前收到的最大offset,从这个 offset 到当前的stream 所能容纳的最大缓存,就是真正的窗口大小。这个方法更准确。

img

小结

  • HTTP 协议三个部分,状态行、首部、实体,状态行中的get、post、put、delete方法。首部中几个重要字段。

  • HTTP2.0 通过HTTP 头压缩,多个stream、分帧、二级制编码,多路复用提升性能。

  • QUIC 协议基于UDP 协议,自己实现四个机制,不需要重连,保证不掉包,控制流量,多路复用。

原文地址:https://www.cnblogs.com/mingjie-c/p/11801672.html