HTTP

简介

HTTPHyper Text Transfer Protocol的缩写,是一种应用层协议,该协议是用于从万维网服务器传输超文本到本地浏览器的传送协议,且它是基于传输层协议TCP/IP通信协议来传递数据

简单来说,它就是一种约定协议,一种客户端跟服务端之间的约定协议

特点:

  • 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
  • 媒体独立灵活):这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送,正在传输的类型由 Content-Type 加以标记,客户端以及服务器指定使用适合的MIME-type内容类型。
  • 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力,这里的状态是指通信过程的上下文信息。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
  • 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快。

缺点

  • 无状态:即使优点也是缺点,缺点在于HTTP 服务器不会保存关于客户的任何信息,比如一个拥有登录态的页面需要发送多个HTTP请求,无状态并无法保存登录状态(HTTP/1.1:Cookie 的出现解决了这个缺点
  • 明文传输:协议中的报文使用的是文本形式,这就直接暴露给外界,不安全。
  • 不安全

(1)通信使用明文(不加密),内容可能会被窃听;

(2)不验证通信方的身份,因此有可能遭遇伪装;

(3)无法证明报文的完整性,所以有可能已遭篡改;

工作方式

<% asset_img image.png HTTP工作方式 %>

由图也能看出来,HTTP是依靠这TCP这些运输层协议进行传输,浅显得理解为,TCP是一个管道,HTTP是其中运输物品的蚂蚁,需要TCP把管道搭建好,小蚂蚁(HTTP)才能运输物品(信息)从客户端到服务端,反之相理

消息结构

客户端请求消息

客户端发送一个HTTP请求到服务器的请求消息包括以下格式:

  • 请求行(request line)
  • 请求头部(header)
  • 空行
  • 请求数据

img

看下实例

GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi

上述的请求信息传递了请求方法为GET,请求的URI为/hello.txt,以及协议版本为HTTP/1.1版本

后面三行都是请求的头部,以键值对的形式存在

服务端响应消息

服务器响应一个HTTP请求返回给客户端的响应消息包括以下格式:

  • 状态行
  • 消息报文
  • 空行
  • 响应体

<% asset_img image(1).png 服务端响应消息 %>

版本更替

<% asset_img image(2).png 版本更替 %>

HTTP/0.9

像是借书一样,这时候的HTTP只做一件事,去图书馆(服务器),拿着书单(请求行),借书(返回html字符流),接完书就走了(断开TCP链接)

<% asset_img image(3).png HTTP/0.9 %>

特点

- 请求方法也只有单纯的GET
- 由于客户端需求比较简单,**只有请求行**就足以表达,并**没有请求体和请求头**
- **服务端也没有头信息返回**,直接返回数据
- **服务器只能返回HTML格式的字符串**,返回文件内容是以ASCII字符流传输
- 当服务器返回数据后断开TCP链接
- 开始有了三件套流程:建立TCP链接,进行数据传输,断开TCP链接

缺陷

- 只能传递返回HTML文件,其他文件如何传输
- 文件格式丰富起来,用ASCII字符流传输无法满足

HTTP/1.0

<% asset_img image(4).png HTTP/1.0 %>

特点

  • 请求方法方面:新增了两种请求方法:POST、HEAD

    HEAD请求:HEAD方法跟GET方法相同,只不过服务器响应时不会返回消息体。一个HEAD请求的响应中,HTTP头中包含的元信息应该和一个GET请求的响应消息相同。这种方法可以用来获取请求中隐含的元信息。也经常用来测试超链接的有效性、可用性和最近的修改

  • 传输内容方面:服务端除了返回字符串,还支持图片、视频、二进制文件

  • 新增了HTTP头信息:新增http头信息来描述元数据信息(请求头,响应头)

    这里的头信息包括但不限于: 请求头: accept:客户端希望服务端返回的文件类型 accept-encoding:压缩方法 accept-Charset:编码方式 accept-language:语言 响应头: content-type:返回的文件类型 content-encoding:压缩方法

  • 新增了缓存机制

  • 文件类型:新增了Content-type请求头参数,用于描述返回数据的文件类型,支持MIME-types

    MIME-type:MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的标准,用来表示文档、文件或字节流的性质和格式。

缺陷

  • 每次进行HTTP通信,仍要执行三部曲(建立TCP链接,传输数据,断开TCP链接),增加多余的开销
  • 要等前面的请求响应,下一个请求才能发送,如果没有及时但会,容易产生队头阻塞
  • 域名跟IP唯一绑定,一个服务器只能有一个域名
  • 响应头必须完整去返回内容长度Content-Length才能正确接受数据,不支持接受动态生成的内容(无法判断大小)
  • 不支持局部数据传输,无法实现断点续传

HTTP/1.1

<% asset_img image(5).png HTTP/1.1 %>

特点

  • 出现了Cookie:引入了Cookie机制安全机制

  • keep-alive长链接

    :头信息的Connection参数

    默认开启

    (HTTP/1.0默认关闭)** **

    Connection:keep-alive
    

    实现了持久链接,使得在头信息传输

    Connection:close
    

    前能对当前的TCP链接进行复用,减少了建立TCP链接和断开TCP链接所产生的消耗和延迟

    • 浏览器对同一个域名,默认允许同时建立6个TCP持久连接
  • 局部资源请求:在请求头上引入了range头域,它允许只请求资源的某一部分,即返回码是206(partial Content),能够支持HTTP/1.0无法支持的动态内容返回,引入了分块传输编码(Chunk transfer)的机制解决该问题,服务器将数据切割成若干个任意大小的数据块,每个数据块发送时带上数据块的大小。

  • 缓存方面:http1.1 则引入了更多的缓存控制策略,例如 Etag、If-Unmodified-Since、If-Match、If-None-Match 等更多可供选择的缓存头来控制缓存策略。

  • 新增了 host 字段:用来指定服务器的域名。http1.0 中认为每台服务器都绑定一个唯一的 IP 地址,因此,请求消息中的 URL 并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机,并且它们共享一个IP地址。因此有了 host 字段,这样就可以将请求发往到同一台服务器上的不同网站。

  • 尝试解决队头阻塞问题,解决方案是:将请求队列(先进先出)转移至服务端的响应队列,但是仍然未解决就是了……

缺陷

  • 队头阻塞仍然未解决
  • TCP的慢启动导致的性能问题,小文件也要花费比较长的时间
  • 多条TCP链接之间竞争带宽,没有优先级

HTTP/2.0

<% asset_img image(6).png HTTP/2.0 %>

特点

  • 二进制协议:HTTP/2 是一个二进制协议。在 HTTP/1.1 版中,报文的头信息必须是文本(ASCII 编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为”帧”,可以分为头信息帧和数据帧。 帧的概念是它实现多路复用的基础。
  • 多路复用:HTTP/2 实现了多路复用,HTTP/2 仍然复用 TCP 连接,但是在一个连接里,客户端和服务器都可以同时发送多个请求或回应,而且不用按照顺序一一发送,这样就避免了队头堵塞的问题。
  • 数据流:HTTP/2 使用了数据流的概念,因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的请求。因此,必须要对数据包做标记,指出它属于哪个请求。HTTP/2 将每个请求或回应的所有数据包,称为一个数据流。每个数据流都有一个独一无二的编号。数据包发送时,都必须标记数据流 ID ,用来区分它属于哪个数据流。
  • 头信息压缩:双端共同维护一张首部表,从而无需每次更新都携带首部
  • 可设置优先级:服务器会优先处理优先级高的(解决HTTP/1.1出现的多条TCP争抢带宽的缺陷)
  • 服务端推送(不再是只有客户端能够主动发送):HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送。使用服务器推送提前给客户端推送必要的资源,这样就可以相对减少一些延迟时间。这里需要注意的是 http2 下服务器主动推送的是**静态资源**,和 WebSocket 以及使用 SSE 等方式向客户端发送即时数据的推送是不同的。

缺陷

  • HTTP/2.0的确解决了前面发生的队头阻塞的问题,但是没法解决TCP(或者说是数据传输过程中)的因为丢包重发导致的队头阻塞
  • TCP建立连接的延时(要造反了,应用层说运输层的不是啦!!)

QUIC

👆🏻点链接,这个大佬的博客讲得很详细,这一段是参考的

QUIC (Quick UDP Internet Connections)是由 Google 从 2013 年开始研究的**基于 UDP **的可靠传输协议

特点

  1. 解决队头阻塞问题(流的多路复用

    <% asset_img image(7).png QUIC流的多路复用 %>

    QUIC进行流传输,流与流之间相互独立,即使出现流的丢包,也不会发生队头阻塞的情况

  2. 流和连接(connection)级别的流量控制

    应用协议通过 QUIC 连接的流(streams)交换信息,流(stream)是有序序列的字节(bytes)。可以创建两种类型的流:双向流(bidirectional streams),允许客户端和服务端互相发送数据。单向流(unidirectional streams),允许单个端点(endpoint)发送数据。一个基于信用的方案(credit-based scheme)用于限制流的创建并限制可发送的数据量。

  3. 低连接延迟损耗

    <% asset_img image(8).png QUIC低连接延迟损耗 %>

    比起TCP+TLS的3-RTT建立连接后才能进行数据传输,QUIC 握手合并了加密和传输参数的协商,只需要 1-RTT 即可可以完成握手,提升了建立连接到交换应用程序数据的速度

  4. 连接迁移(Connection migration)和弹性 NAT 重绑定

    QUIC 连接并不是严格地绑定到一个单一的网络路径(IP:Port)。连接迁移(Connection migration)使用连接 ID 来允许连接转移到新的网络路径。比如手机网络从蜂窝网络(cellular)切换到 WIFI 时,IP 地址改变了,QUIC 可以通过连接迁移(connection migration)来避免连接中断。

  5. 经过身份验证和加密的头部(header) 和有效载荷(payload)

    QUIC 对所有数据包进行身份验证,并尽可能加密,增加了端到端传输的安全性。

    QUIC 使用帧(frames)进行端到端的通信,一个或多个帧(frame)被组装成一个 QUIC 包(packet)。

    帧(Frame):QUIC 数据包(packet)的有效载荷(payload)。

如何断开链接呢?

连接建立之后,可以通过多个选项关闭连接:应用程序可以管理正常(graceful)关闭、端点(endpoints)可以协商超时时间、错误可以导致立即断开连接、无状态(stateless 机制提供了在一个端点失去状态后终止连接的功能。

HTTP/3.0

<% asset_img image(9).png HTTP/3.0 %>

其实其实其实!!HTTP/3.0应该跟HTTPS(HTTP/2.0+TLS)进行比较

特点

  • 基于QUIC协议(不属于一个应用层协议,也不属于一个传输层协议,更像是两层中间的传输协议)
  • 一改以往的TCP传输层协议,使用UDP协议+QUIC解决了HTTP多个版本仍未彻底解决的队头阻塞问题
  • 一改以往的TCP传输层协议利用校验和序列号和确认应答机制重传机制实现的传输可靠性,HTTP/3.0是使用了QUIC中对所有数据包进行身份验证的特点,并尽可能加密实现传输可靠性
  • 一改以往的TCP传输层协议的三次握手建立链接,使用QUIC实现0-RTT或者1-RTT建立连接