Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP/0.9、HTTP/1.0、HTTP/1.1、HTTP/2、HTTP/3、websocket之间的区别 #57

Open
TieMuZhen opened this issue Dec 5, 2021 · 0 comments
Labels

Comments

@TieMuZhen
Copy link
Owner

TieMuZhen commented Dec 5, 2021

HTTP是基于TCP/IP协议的应用层协议,它不涉及数据包的传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。

HTTP/0.9

该版本极其简单,只有一个GET请求。
特点:

  • 只有一个GET请求;
  • 没有 Header 等描述数据的信息;
  • 一旦服务器发送数据完毕,就关闭TCP连接;
  • 典型的无状态
  • 协议规定,服务器只能回应HTML格式的字符串,不能回应别的格式;

HTTP/1.0

相对上一版本:

  • 任何格式的内容都可以发送,这使得互联网不仅可以传输文字,还能传输图像、视频、二进制。
  • 除了GET命令,增加了POST、HEAD等命令,丰富了浏览器与服务器的互动手段;
  • HTTP请求和回应格式也变了,除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据;
  • 增加状态码(status code)、多字符集支持、多部分发送(multi-parttype)、权限(authorization)、缓存(cache)、内容编码
    (content encoding)等;

缺点

HTTP/1.0版的主要缺点是,每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。
TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)。所以HTTP1.0版本的性能较差。随着网页加载的外部资源越来越多,问题就愈发突出。

问了解决这个问题,有些浏览器请求时,用了一个非标准Connection字段:

Connection: keep-alive

这个字段要求服务器不要关闭TCP连接,以便其他请求复用,服务器同样回应这个字段:

Connection: keep-alive

一个可以复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法。

HTTP/1.1

  • 实现持久连接;
  • 管道机制;
  • Content-length字段;
  • 分块传输编码,发送方将数据分成大小不等的数据片发送,避免过大信息引起的负载;
  • 增加了options、put、delete、trace和connect五种请求方法;
  • 新增了24个状态响应码;
  • 客户端请求的头信息新增了Host字段,用来指定服务器的域名;

实现持久连接
1.1版本最大变化,引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive
客户端和服务端发现对方一段时间没有活动,可以主动关闭连接。不过,规范做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接。

Connection: close

目前对于同一个域名,大多数浏览器允许同时建立6个持久连接。

管道机制
1.1版本还引入管道机制(pipelining),即在同一个TCP连接里面,客户端可以同时发送多个请求。这样进一步改进了HTTP协议的效率。

举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求

Content-length

一个TCP连接现在可以传送多个回应,势必就要有一种机制,区分数据包是属于哪一个回应的。这就是Content-length字段的作用,声明本次回应的数据长度。

Content-Length: 3495

上面代码告诉浏览器,本次回应的长度是3495个字节,后面的字节就属于下一个回应了。

在1.0版中,Content-Length字段不是必需的,因为浏览器发现服务器关闭了TCP连接,就表明收到的数据包已经全了。

分块传输编码
使用Content-Length字段的前提条件是,服务器发送回应之前,必须知道回应的数据长度。

对于一些很耗时的动态操作来说,这意味着,服务器要等到所有操作完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用"流模式"(stream)取代"缓存模式"(buffer)。

因此,1.1版规定可以不使用Content-Length字段,而使用"分块传输编码"(chunked transfer encoding)。只要请求或回应的头信息有Transfer-Encoding字段,就表明回应将由数量未定的数据块组成。

Transfer-Encoding: chunked

每个非空的数据块之前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完了。

缺点

复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为"队头堵塞"(Head-of-line blocking)。

为了避免这个问题,只有两种方法:一是减少请求数,二是同时多开持久连接。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等等。如果HTTP协议设计得更好一些,这些额外的工作是可以避免的。

HTTP/2

2015年,HTTP/2 发布。它不叫 HTTP/2.0,是因为标准委员会不打算再发布子版本了,下一个新版本将是 HTTP/3。

  • 二进制协议,所有数据实现二进制传输,传输更加方便;
  • 多路复用,同一个TCP连接内发送多次请求不再需要按照顺序来,实现并行传输,提高效率;;
  • 数据流;
  • 头信息压缩,以减少带宽;
  • 服务器推送;

二进制协议
HTTP/1.1 版的头信息肯定是文本(ASCII编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为"帧"(frame):头信息帧和数据帧。

二进制协议的一个好处是,可以定义额外的帧。HTTP/2 定义了近十种帧,为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。

多路复用
HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了"队头堵塞"。

为什么HTTP/1.1不能实现“多路复用”?
简单回答就是:HTTP/2是基于二进制“帧”的协议,HTTP/1.1是基于“文本分割”解析的协议。

数据流
因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。

HTTP/2 将每个请求或回应的所有数据包,称为一个数据流(stream)。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。

数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。

客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应。

头信息压缩
HTTP 协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如Cookie和User Agent,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。

HTTP/2 对这一点做了优化,引入了头信息压缩机制(header compression)。一方面,头信息使用gzip或compress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。

服务器推送
HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送(server push)。

常见场景是客户端请求一个网页,这个网页里面包含很多静态资源。正常情况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。

HTTP/3

  • 基于google的QUIC协议,而quic协议是使用udp实现的
  • 减少了tcp三次握手时间,以及tls握手时间
  • 解决了http 2.0中前一个stream丢包导致后一个stream被阻塞的问题
  • 优化了重传策略,重传包和原包的编号不同,降低后续重传计算的消耗
  • 连接迁移,不再用tcp四元组确定一个连接,而是用一个64位随机数来确定这个连接
  • 更合适的流量控制

websocket

  • 服务端推送,实现服务端客户端全双工通信,基于TCP。websocket协议实现了客户端和服务端的双向通信,可以建立服务端主动向客户端发送数据。
  • WebSocket是HTML5中新协议、新API。
  • WebSocket是由http先发起的,然后再转为websocket连接。

HTTP 和 HTTPS区别

  • HTTPS是HTTP协议的安全版本,HTTP协议的数据传输是明文的,是不安全的,HTTPS使用了SSL/TLS协议进行了加密处理,相对更安全
  • HTTP 和 HTTPS 使用连接方式不同,默认端口也不一样,HTTP是80,HTTPS是443
  • HTTPS 由于需要设计加密以及多次握手,性能方面不如 HTTP
  • HTTPS需要SSL,SSL 证书需要钱,功能越强大的证书费用越高

参考文献

@TieMuZhen TieMuZhen added the HTTP label Dec 5, 2021
@TieMuZhen TieMuZhen changed the title HTTP/0.9、HTTP/1.0、HTTP/1.1、HTTP/2之间的区别 HTTP/0.9、HTTP/1.0、HTTP/1.1、HTTP/2、HTTP/3、websocket之间的区别 Feb 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant