Skip to content
本页目录

HTTP 相关

一、HTTP/0.9

背景

1991 年提出的 HTTP/0.9,当时主要用于学术交流,需求很简单——用于在网络间传递 HTML 超文本的内容,所以被称为超文本传输协议。

HTTP/0.9 的请求流程

  • 1、因为 HTTP 都是基于 TCP 协议的,所以客户端先要根据 IP 地址、端口号去和服务器建立连接,建立连接的过程就是 TCP 协议三次握手的过程。

  • 2、建立好连接后,会发送一个 GET 请求行的信息,如 GET /index.html 用来获取 index.html。

  • 3、服务器接收到请求信息后,读取对应的 HTML 文件,并将数据以 ASCII 字符流返回给客户端。

  • 4、服务器发送完成后,断开 HTTP 连接。

HTTP/0.9 的主要特点

  • 1、只有请求行,没有请求头和请求体

  • 2、服务器也不会返回头信息,只会返回数据。

  • 3、服务器返回的数据是以 ASCII 字符流来传输的,因为都是 HTML 格式的文件,所以用 ASCII 字节码来传输是最合适的。

二、HTTP/1.0

HTTP/1.0 的主要特点

  • 1、HTTP1.0 引入了请求头和响应头支持传输多种类型的文件。

  • 2、HTTP1.0 引入了状态码,User-Agent 请求头字段也是 1.0 加入的。还引入了 POST 和 HEAD 方法。

状态码是通过响应行的方式来通知浏览器的。User-Agent 请求头可以统计客户端的基础信息,比如 Windows 和 macOS 的用户数量分别是多少等。

  • 3、为了减轻服务器的压力,在 HTTP/1.0 中提供了 Cache 机制,用来缓存已经下载过的数据。

  • 4、HTTP/1.0 每次进行一次 HTTP 通信都要经历建立 TCP 连接、传输 HTTP 数据、断开 TCP 连接三个阶段。重复的步骤会浪费好多时间。(缺点)

三、HTTP/1.1

持久连接

它的特点是在一个 TCP 连接上可以传输多个 HTTP 请求,只要浏览器或者服务器没有明确断开连接,那么该 TCP 连接会一直保持。HTTP 的持久连接可以有效减少 TCP 建立连接和断开连接的次数,这样的好处是减少了服务器额外的负担,并提升整体 HTTP 的请求时长。 持久连接在 HTTP/1.1 中是默认开启的,所以你不需要专门为了持久连接去 HTTP 请求头设置信息,如果你不想要采用持久连接,可以在 HTTP 请求头中加上 Connection: close。目前

队头阻塞与不成熟的 HTTP 管线化

虽然 HTTP/1.1 增加了持久连接的能力,减少了 TCP 连接和断开的次数,但是它还是要等待前一个 HTTP 请求返回之后才能进行下一个 HTTP 请求。想象一下如果某个 HTTP 请求因为某些原因没有及时返回,那么这个请求之后的所有 HTTP 请求都会被堵住,这就是常说的问题。

HTTP/1.1 试图通过管线化的技术来解决队头阻塞的问题。HTTP/1.1 中的管线化是指将多个 HTTP 请求整批提交给服务器的技术,虽然可以整批发送请求,不过服务器依然需要根据请求顺序来回复浏览器的请求。

域名分片

在 HTTP/1.0 中,每个域名都绑定了一个唯一的 IP 地址,因此一个服务器只能为一个域名服务。随着虚拟主机技术的发展,实现了在一台物理主机上绑定多个虚拟主机,每个虚拟主机对应一个单独的域名,这些域名共用一个 IP 地址。因此,

Chunk transfer 机制

在设计 HTTP/1.0 时,需要在响应头中设置完整的数据大小,如 Content-Length: 901,这样浏览器就可以根据设置的数据大小来接收数据。不过随着服务器端的技术发展,很多页面的内容都是动态生成的,因此在传输数据之前并不知道最终的数据大小,这就导致了浏览器不知道何时会接收完所有的文件数据。

HTTP/1.1 通过引入 Chunk transfer 机制来解决这个问题,服务器会将数据分割成若干个任意大小的数据块,每个数据块发送时会附上上个数据块的长度,最后使用一个零长度的块作为发送数据完成的标志。这样就提供了对动态内容的支持。

  • 5、新增方法:PUT、 PATCH、 OPTIONS、 DELETE。

四、HTTP/2.0

多路复用机制

HTTP/1.1 对带宽的利用率并不理想,原因主要有三个。

  • TCP 的慢启动机制
  • 多个 TCP 连接竞争带宽资源
  • HTTP/1.1 队头阻塞的问题

HTTP/2.0 的解决方案:多路复用机制(通过引入了二进制分帧层实现)

  • 首先,浏览器准备好请求数据,包括了请求行、请求头等信息,如果是 POST 方法,那么还要有请求体。
  • 这些数据经过二进制分帧层处理之后,会被转换为一个个带有请求 ID 编号的帧,通过协议栈将这些帧发送给服务器。
  • 服务器接收到所有帧之后,会将所有相同 ID 的帧合并为一条完整的请求信息。
  • 然后服务器处理该条请求,并将处理的响应行、响应头和响应体分别发送至二进制分帧层。
  • 同样,二进制分帧层会将这些响应数据转换为一个个带有请求 ID 编号的帧,经过协议栈发送给浏览器。
  • 浏览器接收到响应帧之后,会根据 ID 编号将帧的数据提交给对应的请求。

头部压缩

  • 无论是 HTTP/1.1 还是 HTTP/2,它们都有请求头和响应头,这是浏览器和服务器的通信语言。HTTP/2 对请求头和响应头进行了压缩。

  • HTTP 1.1 版本会出现 「User-Agent、Cookie、Accept、Server、Range」 等字段可能会占用几百甚至几千字节,而 Body 却经常只有几十字节,所以导致头部偏重。HTTP 2.0 使用 HPACK 算法对头部进行压缩,节省空间。

请求优先级

为了避免重要的请求得不到服务器的优先处理,HTTP/2 提供了请求优先级,可以设置请求的优先级。

服务器推送

除了设置请求优先级之外,HTTP/2.0 还可以直接将数据提前推送到浏览器。

场景

用户请求一个 HTML 页面之后,服务器知道该 HTML 页面会引用几个重要的 JavaScript 文件和 CSS 文件,那么在接收到 HTML 请求之后,附带将要使用的 CSS 文件和 JavaScript 文件一并发送给浏览器,这样当浏览器解析完 HTML 文件之后,就能直接拿到需要的 CSS 文件和 JavaScript 文件,这对首次打开页面的速度起到了至关重要的作用。

五、HTTP header 有哪些字段

六、HTTP 有哪些请求方法

  • GET 方法 请求一个指定资源的表示形式. 使用 GET 的请求应该只被用于获取数据。

  • HEAD 方法 请求一个与 GET 请求的响应相同的响应,但没有响应体。

    • HEAD 方法和 GET 方法差不多,都是发送请求并从服务器获取数据。但服务器并不会返回请求的实体数据,只会传回响应头,也就是资源的“元信息”。(幂等方法)

    • 你也可以理解为 HEAD 方法是 GET 方法的简易版,它的响应头与 GET 完全相同。

    • 一般可以用在很多并不真正需要资源的场景,避免传输 body 数据造成不必要的资源浪费。

    • 举两个例子:

    • 1、检查一个文件是否存在可以用 HEAD 请求,没有必要用 GET 把整个文件都取下来。

    • 2、检查文件是否有最新版本,也可以使用 HEAD,服务器会在响应头里把文件的修改时间传回来。

  • POST 方法 用于将实体提交到指定的资源,通常导致在服务器上的状态变化或副作用。

  • PUT 方法 用请求有效载荷替换目标资源的所有当前表示。

  • DELETE 方法 删除指定的资源。

  • CONNECT 方法 建立一个到由目标资源标识的服务器的隧道。

  • OPTIONS 方法 用于描述目标资源的通信选项。

  • TRACE 方法 沿着到目标资源的路径执行一个消息环回测试。

  • PATCH 方法 用于对资源应用部分修改。

七、何谓简单请求

一个 HTTP 请求如果满足以下所有要求,则该请求为简单请求(跨域不会发预检请求)。

  • 1、使用下列方法之一:

    • GET
    • HEAD
    • POST
  • 2、除了被用户代理自动设置的首部字段(例如 ConnectionUser-Agent)之外,只能是以下首部字段:

    • Accept: 请求头用来告知(服务器)客户端可以处理的内容类型。
    • Accept-Language: 请求头允许客户端声明它可以理解的自然语言,以及优先选择的区域方言。
    • Content-Language: 用来说明访问者希望采用的语言或语言组合,这样的话用户就可以根据自己偏好的语言来定制不同的内容。
    • Content-Type: 实体头部用于指示资源的 MIME 类型。
  • 3、Content-Type 的值仅限于下列三者之一:

    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded

MIT Licensed