HTTP协议之基础入门

312 阅读10分钟

什么是HTTP?

HTTP是TCP/IP基于应用层的通信协议,用于标准化客户端和服务端之间的通信方式。它定义了如何请求和传输内容。默认TCP端口为80,当然也可以使用其他端口。(HTTPS的默认端口为443)

HTTP/0.9

1991年,提出了HTTP的第一个版本HTTP/0.9。它是有史以来最简单的协议。只有一个GET方法。如果客户端像服务端请求一个网页,将会发出如下简单的请求:

客户端请求:

GET /index.html

服务器响应:

(response only)
(connection closed)

如上,服务器获取到请求,将HTML响应作为请求,一旦内容传输完,连接将被关闭。

总结:

  • 没有请求头
  • 只有一个GET方法
  • 响应必须是HTML

HTTP/1.0

1996年,HTTP/1.0被提出,与HTTP/0.9有了很大的改进。 与HTTP/0.9仅针对HTML响应设计的不同,HTTP/1.0可以处理其他响应格式,如图像,视频文件,纯文本和任何其他内容类型。并且添加了POSTHEAD方法,更改了请求和响应格式,在请求和响应都添加了HTTP请求头,添加了状态码和表示响应,引入字符集,multi-part类型,授权,缓存,内容编码等。

HTTP/1.0 请求如下:

GET / HTTP/1.0
Host: dpplh.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36
Accept: */*

综上,除了请求以外,还发送了客户端信息和所接受的响应类型。

响应如下:

HTTP/1.0 200 OK 
Content-Type: text/plain
Content-Length: 137582
Expires: Mon, 04 Jan 2021 06:54:02 GMT
Last-Modified: Sat, 04 Jan 2020 01:50:20 GMT
Server: sffe

(response body)
(connection closed)

在响应最开始有HTTP/1.0(HTTP,后接版本号),然后是状态码

在此叫新版本中,请求和响应头仍保持ASCII编码状态,但是响应主体可以是任何类型,即图像,视频,HTML,纯文本和其他任何内容类型。因此,现在服务器可以将任何内容类型发送到客户端。

HTTP/1.0主要缺点之一就是每个连接不能有多个请求。也就是每当客户端需要服务器中的某些内容,都必须开启新的TCP连接,并且在满足单个请求之后,连接被关闭。对于任何下一个请求,都必须建立在新连接上。每次的TCP连接都需要三次握手,会有严重的性能问题。

某些在HTTP/1.0 尝试通过引入一个新的标头,Connection: keep-alive,用来告诉服务器不要关闭连接,但是并没有得到广泛支持,问题仍然存在。

HTTP除了无连接之外,还是一种无状态协议,即服务器不维护有关的客户端信息,因此每个连接都必须含有服务器所需要的客户端信息,并且不与之前任何一个旧的请求有关联。因此除了客户端必须建立大量连接之外,还需要在请求过程中发送一些冗余的数据,增加了带宽的占用。

HTTP/1.1

1999年,仅过了三年,HTTP/1.1就发布了,在HTTP/1.0的基础上做了很多的改进。

  • 新的HTTP请求方法:PUT、PATCH、OPTIONS、DELETE

  • Host主机名标识,在HTTP/1.0不是必须的,但在HTTP/1.1变成必须的

  • 持久连接,在HTTP/1.0每个连接中只有一个请求,并且一旦没出请求,连接就会被关闭,这会导致性能下降和延迟问题。HTTP/1.0加入了持久连接,即默认情况下未关闭连接并且保持打开状态,从而允许多个顺序请求。如果要关闭连接,Connection: close。客户端通常在最后一个请求中发送此标头,以安全关闭连接。

  • 流水线化:客户端可以向服务器发送多个请求,而不必等待来自同一个连接上的服务器响应,并且服务器必须保持接收请求的相同顺序发送响应。

在流水线化中,客户端怎么知道第一个响应下载完成且下一个响应内容开始? 此时必须提供Content-Length标头,客户端可以使用该标头来标识响应的结束位置,并且可以开始等待下一个响应。

疑问:如果数据是动态的并且服务器无法预知内容长度,该怎么办呢?

为了解决这个问题,HTTP/1.1引入了分块编码。在这种情况下,服务器可能会省略Content-Length,而推荐使用分块编码。但是,如果他们都不可用,则必须在请求结束时关闭连接。

  • 分块传输如果是动态内容,则当服务器无法真正确定Content-Length传输开始的时间时,它可能会开始分块发送内容,并在Content-Length发送时为每个块添加内容,并且当前所有块都以发送(即整个传输已完成)时,它会发送一个空块(Content-Length即将设置为零),以表示传输以完成的客户端。为了通知客户端分块传输的信息,服务器需包含标头Transfer-Encoding: chunked
  • 与HTTP/1.0仅具有基本身份验证的情况不同,HTTP/1.1包括摘要身份验证和代理身份验证
  • 缓存
  • Byte Range
  • 字符集
  • 语言
  • Cookie
  • 更强的压缩支持
  • 新的状态码
  • ...

SPDY

SPDY是Google在2019年为了提高网络速度,并在降低网络延迟的同时提高网络安全性时提出的。这个协议在Chrome浏览器证明可行后,就被当作HTTP/2的基础,主要特性都在HTTP/2中被继承。

SPDY里的预置字典为头部特殊设计的,但它使用的仍然是DEFLATE算法,其中包括动态Huffman编码以及字符串匹配。但是因为DEFLATE算法使用的是落后的字符串匹配以及动态Huffman编码,攻击者可以从压缩头部提取密钥认证cookies,从而很容易进行犯罪行为。攻击者还可以控制部分请求头,并且修改部分请求来找回整个cookie以及观察到再压缩情况下请求改变的总大小。

HTTP/2.0

HTTP/2.0设计用于低延迟的内容传输,与HTTP/1.1的不同之处:

1. 二进制协议:头和数据体都是二进制

HTTP/2.0主要构件模块是帧和流,二进制协议易于解析,解决HTTP/1.x存在的延迟问题。

帧和流

HTTP消息由一个或者多个帧组成。有一个HEADERS用于元数据和帧DATA帧的有效载荷,并存在集中其他类型的帧(HEADERS,DATA,RST_STREAM,SETTINGS,PRIORITY...)。

每个HTTP/2.0请求和响应有一个唯一的ID,并将其划分为帧。每个帧即二进制数据,帧的集合为流,并且每个帧都有一个公共的头。

客户端发起的任何请求都是使用的奇数,服务端的响应具有偶数流ID

除了HEADERSDATA,还有一种特殊的帧类型RST_STREAM,用于终止某些流,即客户端可以发送该帧让服务器知道不再需要该流。

HTTP/1.1中,服务器停止发送到客户端的响应被关闭,导致轻微的延迟。因为每个新的请求都需要重新连接。HTTP/2.0中,客户端使用RST_STREAM来通知服务器并停止接收特定的流,同时连接不断开,可以继续接收其他的流。

2. 多路复用:通过单个连接的多个异步HTTP请求

使用帧和流进行请求和响应,所以一旦打开TCP连接,所有流都将通过同一连接异步发送,无需额外的连接。相反,服务器以相同的异步方式进行响应,即响应没有顺序,客户端使用分配的流ID来表示特性数据所属的流,这样就解决了HTTP/1.x中存在的行头阻塞问题。

3. 使用HPack进行头部压缩

当我们不断的从客户端访问服务器时,会反复的发送大量的冗余数据,有时还可能会出现cookie,这回增加头部大小,导致带宽使用和延迟增加。

与请求和响应不同,标头不采用gzipcomparess的格式进行压缩,而是如下三种压缩方法:

  • 静态字典:一个有着61个通用头部字段,并且部分字段是有预定义值的预定义字典。
  • 动态字典:在连接中,一些列实际的头部会被添加进去。因为字典有限制大小,所以当新项被增加,旧项就会被移除。
  • Huffman编码:一种可以被用来对任何字符串:Key or Value,进行编码的静态Huffman编码。这种编码方式专门为HTTP响应或者响应头设计的——ASCII里的数字和字母可以更短。

4. 服务器推送:单个请求多个响应

HTTP/2.0允许再客户端未经请求,主动向客户端发送资源。

5. 请求优先级

客户端在可以发送PRIORITY帧来更改流的优先级。如果没有优先级信息,则服务器异步处理请求,即没有任何顺序。如果分配了优先级,则服务器根据此优先级信息确定需要分配多少资源来处理哪个请求。

MIME Types

text/plain
text/html
image/jpeg
image/png
audio/mpeg
audio/ogg
audio/*
video/mp4
application/*
application/json
application/javascript
application/ecmascript
application/octet-stream
…
类型 描述 事例
text 普通文本 text/plain,
text/html,
text/css,
text/javascript
image 图像;不包括视频,但是Gif也是用image类型 image/gif,
image/png,
image/jpeg,
image/bmp,
image/webp,
image/x-icon,
image/vnd.microsoft.icon
audio 音频文件 audio/midi,
audio/mpeg,
audio/webm,
audio/ogg,
audio/wav
video 视频文件 video/webm,
video/ogg
application 二进制数据 application/octet-stream, 
application/xhtml+xml, 
application/xml, 
application/pdf

对于text类型的文件如果没有特定的subtype,默认使用text/plain。二进制文件没有特定或者已知的subtype,默认使用application/octet-stream

重点的MIME类型

1、 application/octet-stream

这是应用程序文件的默认值,意思是未知的应用程序文件,浏览器一般不会自动执行和询问执行。

2、 text/plain

文件的默认值,即使它意味着位置的文本文件,浏览器也可以直接展示。

3、 text/css

在网页中要被解析为css的任何css文件,都必须制定MIME为text/css。通常情况下浏览器不识别.css为后缀的文件MIME类型,而是将其以MIME为text/plain或application/octet-stream来发送给浏览器。

4、 text/html

所有的HTML内容都应该使用这种类型。XHTML的其他MIME类型(如application/xml+html)现在基本不使用。

5、 图片类型

MIME类型 图片类型
image/gif GIF图片
image/jpeg JPEG图片
image/png PNG图片
image/svg+xml SVP图片(矢量图)

6、 音视频类型

MIME类型 音视频类型
audio/wave
audio/wav
audio/x-wav
audio/x-pn-wav
音频流媒体文件,一般支持PCM编码
audio/webm WebM音频文件格式
video/webm 采用WebM视频文件格式的音频文件
audio/ogg 采用OGG多媒体文件格式的音频文件
video/ogg
application/ogg
采用OGG多媒体文件格式的音视频文件