HTTP基本学习与演变中(HTTP/0.9,HTTP/1.0,HTTP/1.1,HTTP/2.0,HTTPS)的比较

HTTP(超文本传输协议)

HTTP由两个程序实现,一个用户程序和一个服务器程序,客户程序和用户程序运行在两个不同的端系统,通过交换HTTP报文进行对话。
HTTP协议是基于TCP协议出现的,

HTTP/0.9

HTTP0.9时最早诞生的,于1991年被提出,主要用于学术交流,它只是用来在网络之间传输HTML超文本的内容,所以也被称为超文本协议
当时的HTTP并没有向我们现在一样,用来传输很多类型的文件,所以也很简单,所以当时的HTTP/0.9有下面几个特点

  • 只有一个请求行,没有请求头和请求体
  • 服务器没有返回头信息,只返回需要的数据
  • 返回的文件内容都是通过ASCII字符流的形式传输的
    请求流程如下
  • 客户端根据IP地址、端口和服务器通过三次握手建立TCP连接
  • 建立连接之后,就会发送一个GET请求行的信息来获取html文件
  • 服务器收到相应的信息后,找到对应的HTML文件,将数据以ASCII字符流的形式发送回去
  • 客户端获取到HTML文件,结束连接

HTTP协议格式

在HTTP1.0之后,HTTP的协议格式就变成了下面
在这里插入图片描述

通用首部字段

Cache-Control:该字段用于控制缓存的时效性,由多个参数可选,通过“,”分隔

  • no-cache:在客户端表示强制向源服务器再次验证资源,通过这种方式保证不使用过期的缓存,从源服务器获取资源,如果源服务器返回的响应状态码为304,表示资源可被缓存,即使用本地缓存,但是每次使用都需要和源服务器确认内容
  • no-store:真正意义上的不进行缓存
  • public:表示除了接收该响应的客户端可以使用缓存外,其他用户也可以使用该缓存
  • private:表示只有特定的用户可以接收到缓存服务器提供的缓存资源,对于指定外的用户,无法接收到缓存资源
  • max-age:表示在该指令对应的数值时间内,客户端直接使用代理服务器提供的缓存资源,如果指定max-age为0,缓存服务器则会直接将请求发给源服务器。在超出max-age的情况下向服务端发起新的请求,请求失败的情况下返回缓存数据,否则向服务端重新发起请求。要注意的是,如果同时存在Expires首部字段,在HTTP/1.1中,会优先处理max-age指令,而忽略掉Expires指令;而在HTTP/1.0中正好相反,max-age指令会被忽略掉。
  • s-maxage:和max=age指令的功能相同,但s-maxage只适用于供多位用户使用的公共缓存服务器,对于向同一用户重复返回响应的服务器来说,这个指令没有任何作用,而当这个指令有效时,会忽略expires和max-age
  • min-fresh:要求缓存服务器返回再过指定事件后还在有效期限的资源,比如指定min-fresh为60秒,那么就会返回再过60秒后还在有效期限内的资源
  • max-stale:指示缓存资源,即使过期也照常接收,如果该指令未指定数值,那无论过多久客户端都会接收该响应;如果指令中制定了具体数值,那么只要处于max-stale指定的时间内,即使过期资源也会被客户端接收。该字段在请求中设置有效,在响应中设置无效;max-age和max-stale在请求中同时使用的情况下,缓存的时间可以为max-age和max-stale的和
  • no-transform:规定无论是在请求中还是在响应中,缓存都不能改变实体主体的媒体类型,这样做可防止缓存或代理压缩图片等类似操作

Connection:Connection有两个作用,一个是控制不再转发的首部字段,该作用体现在请求中,使用Connection指定另一个首部字段,在通过代理服务器转发时,就会将该首部字段删除后再转发请求。如果直接发给源服务器,则不会删除相应的字段。比如我们常见的Upgrage,用于告知服务器通信协议修改,我们在进行websocket连接时报文就会包含下面的内容
connection:Upgrade
Upgrage:websocket
如果是通过代理服务器发送的话,在代理服务器发送出去的报文上面的内容就会被删除

第二个作用是管理持久连接,在HTTP/1.1之前的HTTP版本的默认连接都是非持久性连接,若要在旧版本的HTTP上使用持久连接,就要指定该字段值为Keep-Alive。在HTTP/1.1版本后,默认连接都是持久连接。当服务器要断开连接时,可通过指定首部字段的值为Close来断开连接
Date:创建HTTP报文的时间

Via:用于追踪客户端与服务器之间的请求和响应报文的传输路径。每当报文经过代理或网关时,会在首部字段Via中附加该服务器的信息,然后再进行转发。

请求头(Request Header)

Accept:浏览器接收的格式,如text/html;为客户端向服务器提出的想要接收的格式,可以设置多个,然后通过权重的设置来决定优先使用哪种格式。
Accept-Charset:浏览器接收的字符集及字符集的相对优先顺序,如iso-8859-5

Accept-Encoding:浏览器接收的编码格式,如gzip

Accept-Language:浏览器接收的语言,如zh-cn

Authorization:用于告知服务器,用户代理的认证信息。通常在收到401状态码响应后将改字段加入请求中。

Cookie:接收到服务器传来的cookie后,之后每次都将接收到的值放在Cookie字段中发送给服务器。

Host:请求的资源所处的互联网主机名和端口号。为HTTP/1.1新增的字段,在HTTP/1.0中,认为每个服务器对应一个IP地址,所以请求中没有必要写主机名,但是虚拟技术的发展带来了虚拟主机,在HTTP/1.1中,如果没有Host头域,则会报400错误。(如果服务器未设定主机名,则直接发送一个空值)

If-Match:附带条件之一,告知服务器匹配资源所用的实体标记值(ETag)。服务器通过比对If-Match的值和ETag的值,二者相同则正常处理,否则返回412错误(请求头中的一些前提条件失败),这时服务器无法使用弱ETag值。可以通过指定*为字段值来让服务器忽略ETag的存在,只要资源存在就处理请求。

If-None-Match:与If-Match正好相反,仅当字段值与ETag不同时才处理。

If-Modified-Since:指定一个时间,如果在这个时间后资源发生了更新,则服务器会接收请求,返回200同时返回Last-Modified指明上次修改页面的时间,否则返回304。

If-Unmodified-Since:该字段的作用与If-Modified-Since正好相反,仅当指定的请求资源在字段值指定的时间之后才处理请求,否则返回412

User-Agent:客户端标识。会将创建请求的浏览器和用户代理名称等信息传达给服务器。如:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3730.400 QQBrowser/10.5.3805.400

响应头(Response Header)

ETag:告知客户端实体标识。将资源以字符串的形式做唯一标识,服务器为每份资源分配对应的ETag值,生成ETag时,并没有统一的算法规则,而仅仅是由服务器来分配。但是服务器在分配时,可以由服务器来通过算法规则实现分配。所以ETag不变的情况下,资源不一定不变

当资源被缓存时,就会被分配唯一标识,而更新时,ETag值会发生变化,所以通过ETag值我们可以判断资源是否发生了更新。

  • 强ETag,不论实体发生什么细微变化值都会发生改变
  • 弱ETag,仅用于提示资源是否相同,只有资源发生了根本变化时值才会改变,弱ETag值在字段值最开始处会附加W/。

Expires:GMT格式的过期时间,用于判断下次请求是否需要到服务端返回页面。但是这个时间是一个绝对时间,当服务器时间和客户端时间存在较大偏差的时候,就会导致缓存混乱。而实际上服务器和客户端的实际时间不一样是很常见的。
Keep-Alive:持久连接需要的一些信息,如Keep-Alive:timeout=10.max=500,通常在请求中包含字段Connection:Keep-Alive时返回
Last-Modified:页面上次修改的时间
Server:告知客户端当前服务器上安装的HTTP服务器应用程序的信息,还可能包括版本好和安装时启用的可选项。
Set-Cookie:用于设置cookie,可同时设置多个cookie

HTTP/1.0和HTTP/1.1的主要区别

1. 缓存处理

在HTTP1.0中,我们采用Set-Cookie,Expires,Last-Modified,If-Modified-Sinced等字段来处理缓存,在HTTP1.1中,增加了更多字段来处理缓存,如ETag,If-Match,If-None-Match,If-Unmodified-Since,Cache-Control

2. 带宽优化

在HTTP1.0中,即使客户端只是需要对象的一部分,也必须请求整个对象,这样造成了一定的带宽浪费,而在HTTP1.1中,可以通过Range来指定需要哪部分的内容,来获取对象的一部分,请求处理成功后会返回206(只返回资源的部分),若无法处理该范围请求时,则返回状态码200及全部资源。

3. 新增状态码

在HTTP1.1中,增加了很多新的状态码,举几个例子:

4. Host头域

在HTTP/1.1中,多了Host字段,而且这个字段是必传的,即使没有指定的主机,也要发送一个值为空的Host字段,如果没有发送该字段,会返回400状态码(请求的语法错误)

5. 长连接

在HTTP/1.0中,默认的连接方式为短连接,而在HTTP/1.1中,默认的连接方式为长连接,只有在返回字段Connection:close时才会断开连接,而在HTTP/1.0中,需要通过Connection:Keep-Alive来创建长连接

6. 对动态生成的内容提供支持

在HTTP/1.0中,需要在响应头设置完整的数据大小,比如Content-Length:901,但是随着服务端技术的发展,很多内容都是动态生成的,我们无法在传输数据之前知道数据的大小,所以HTTP/1.1引入了Chunk transfer机制来解决这个问题,服务器会将数据分割成若干个任意大小的数据块,每个数据块发送时会附上上个数据块的长度,最后用一个零数据块长度的块做为发送数据结束的标志。

HTTPS

在HTTP的基础上,HTTPS和HTTP/2规定了更复杂的内容,但是保留了HTTP的Request-Response模式
HTTPS有两个作用,一是确定请求的目标服务端身份,二是保证传输的数据不会被网络中间节点窃听或者篡改。
HTTPS是使用加密通道来传输HTTP的内容。但是HTTPS首先与服务端建立一条TLS加密通道。TLS构建于TCP协议之上,它实际上是对传输的内容做一次加密,所以从传输内容上看,HTTPS跟HTTP没有任何区别。
有关于HTTPS的加密,可见我的另一篇博客从HTTP的安全问题到HTTPS


HTTPS与HTTP的一些区别

HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。

HTTP协议运行在TCP之上,所有传输的内容都是明文,HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的。

HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。


HTTP/2.0

HTTP/2.0对HTTP/1.1又做了一些改进,我对这些改进做了自己大致的理解概述

1.服务端推送

服务端推送能够在客户端发送第一个请求到服务端时,提前把一部分内容推送给客户端,放入缓存当中,这可以避免客户端请求顺序带来的并行度不高,从而导致的性能问题。
举个简单的例子,我们在写页面时,一个index.html可能会引入多个css文件,js文件,一般情况下,我们会向服务器请求一个index.html,然后在html中,通过link,script等这些标签,向服务器发起请求去获得这些资源。
而在服务端推送中,我们向服务器发送index.html后,服务端判断,我们还需要css文件,js文件,就将相关的文件一并发送到客户端,这样就减少了后续客户端的请求,提高了整个页面的加载速度。
当然,判断哪些资源需要用到也是一个问题,如果服务端推送了我们不必使用到的资源,反而会造成网络带宽的浪费,降低了页面的加载速度。

2.支持TCP连接复用

我们对从HTTP/1.0以来的连接方法进行比较

短连接

在HTTP/1.0中,我们每次发起请求之前,都要先进行一次TCP连接,在请求发送响应完毕后,我们就要将该连接断开,这种做法当有多个请求都是发往同一个服务器时,仍需要连接多次,关闭多次,相当浪费时间

长连接

长连接解决了短链接多次开启连接,多次关闭连接的问题。在长连接中,我们可以在一次连接中发起多次请求,这样就减少了连接的时间,但存在的问题是,在长连接中,连接的发起是按序单线程发起的。即是说,仅当上一个请求得到响应的时候,我们才能发起下一个请求,这样导致的问题是,一旦有某个请求超时,后面的请求就会被阻塞了
对于这个问题,我们可以采用建立多个长连接来做到一定的并行,浏览器也支持发起一定数量的并行HTTP请求,当然,当这些并行的HTTP请求都在等待响应时,其他请求还是要做等待,而且开启多个HTTP请求本身也造成了多次三次握手的损耗,所以只能说是一定的并行

连接复用

TCP连接复用,则使用同一个TCP连接来传输多个HTTP请求,减少了TCP连接建立时的三次握手开销,和初建TCP连接时传输窗口小的问题。同时,这多个HTTP请求,是可以并行执行的,即便某个请求超时,也不会影响到其他请求的正常发起

而之所以能使用同一个TCP连接来发起多个HTTP请求,是因为在HTTP2.0中,引入了帧和流的概念

  • 帧:在传输过程中最小的数据单位,每个帧会标识出该帧处于哪个流,且在传输中的顺序
  • 流:可以看出是多个帧组成的数据流,在HTTP2中,同一个TCP连接可以有多个流,这也就是可以进行多路复用的原因

3.头部压缩

在一个请求中,包含状态行、请求/响应头部、主体。一般来说主体会经过压缩,但是状态行和请求/响应头部却没有进行压缩。而随着现在Web应用的不断发展,我们发送的请求越来越多了,请求/响应头部的大量传输,也占用了大量的带宽,对这部分内容进行合理地压缩,也能有效地提高页面的加载速度
那么在HTTP/2.0中是如何压缩的,举个例子来说,一个method,可以是get,可以是post,虽然很短,但是可以更短,我们只要做一个字典,使得0表示get,1表示post,就可以对这部分内容进行合理压缩了,这样子,我们只需要在第一次传输的时候,将字典传输过去,每次有新的内容,就添加到字典中,这样子就能减少传输时的带宽。
当然,一个method是不能减少太多,但是如果是一个cookie,那就完全不一样了,我们还每次都要带上这个cookie,如果这个cookie过长,那对我们的传输效率还是会造成影响的,所以头部压缩的作用显而易见

4.可以设置请求的优先级

我们知道,在浏览器第一次进行页面渲染的时候,有的资源会阻塞渲染,有的不会,比如css文件,为了生成CSSOM树来和DOM树结合生成布局树,在渲染时css文件的下载会阻塞整个渲染流程,而图片资源,却不会造成影响,而如果HTTP优先去请求图片,那么也会对渲染造成阻塞,但HTTP又无法识别哪个资源应该优先

为了解决这个问题,在HTTP/2.0中,提供了对请求的优先级设置的功能,这样我们就能对一些会阻塞页面渲染的资源优先请求,尽可能减少页面渲染的时间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值