转载声明:文章来源https://blog.csdn.net/m0_56602092/article/details/129622163
一、HTTP的概念
HTTP是超文本传输协议,是一种应用层协议,是基于为浏览器/服务器间提供统一的信息交换格式而出现的,其发展历程为HTTP/1.0、HTTP/1.1、HTTP/2、HTTP/3。
1. HTTP版本区别
HTTP/1.0:HTTP/1.0为短连接,即客户端单次请求后就关闭TCP连接。这样效率显然是很低的
HTTP/1.1:HTTP/1.1默认为长连接,提升了连接的利用率,可用报文中Connecton字段控制的,取值Keep-Alive 为长连接(默认),取值Close 表示关闭长连接。并且引入了管道化技术,发送请求后不必等待响应就可以继续发送下一个请求,但是由于性能原因很少被支持。
HTTP/2:HTTP/1为半双工,只能由客户端向服务端发送请求,服务端再响应请求。并且HTTP/1.1存在应用层队头阻塞和报文头部信息重复传输的问题。HTTP/2引入了全双工,服务端也可主动发送数据。并且HTTP/2通过将报文分帧传输的方式,实现了连接的多路复用,解决了应用层面的队头阻塞问题。此外,HTTP/2通过HPACK算法对HTTP报文头部进行了压缩,提升了传输效率
HTTP/3:在HTTP/3之前,HTTP都是基于TCP传输的。HTTP/3基于UDP传输
2. HTTP2 vs HTTP1.1
HTTP1.1存在的问题,HTTP1.1引入了长连接,但仍存在一些问题:
应用层队头阻塞:在一条连接中,客户端必须等待获取完一个请求的全部响应报文才能获取下一个请求的响应报文。如果说前一个请求需要的响应时间特别久比如说是一个大文件,后面的请求响应只能被阻塞。
报文头部信息重复传输:由于HTTP本身是无状态协议,每次请求响应都需要带上全部的头部信息,并且这些头部信息中很多都是重复不变的,比如UserAgent,或者每个字段的名称。这些头部信息的重复传输就造成了资源的浪费。
半双工:不支持服务器推送消息, 因此当客户端需要获取通知时,只能通过定时器不断地拉取消息,这无疑浪费大量了带宽和服务器资源。
为了应对这些问题常见的优化方案如下:
减少请求数量:将请求的资源文件内联合并为一个请求响应。
增加连接个数:可以开多个TCP连接去分别进行请求,但是浏览器对一个域名的并发TCP连接数限制为6个,因此还有一些解决方案就是不同资源类型放到不同的二级域名下面,比如像图片这种消耗比较大的资源单独放到一个域名下,这样就可以增加并发的TCP连接数。但是大量的TCP连接的创建与销毁肯定是存在性能问题的,单个TCP连接的利用率还是没有提上去。前面提到的两个问题还是没有完全解决。
HTTP2做了如下改进:
报文分帧传输:在应用层将一个报文视为一个stream流,将报文拆分为多个有序的帧,每个帧的stream流id相同,帧id不同。那么在接收方就可以通过流id区分一个报文,并通过帧id将报文按序组装起来。因此在一个连接中就可以同时传输多个请求或者响应,就是多个报文的帧混合传输,接收端根据id在应用层进行组装,这样实现了连接的多路复用,有效提升了TCP连接的利用率。
报文头部压缩算法:使用HPACK算法对报文头部进行压缩。使用静态表存储常见的HTTP字段和值,用动态表存储请求过程中动态的字段和值,并且使用哈夫曼编码压缩字符串值。那么在传输过程中只需要用对应的表索引来替代实际的值,这样就大大减少了报文头部的大小。
支持全双工:服务器支持主动推送资源,大大提升了消息的传输性能,服务器推送资源时,会先发送 PUSH_PROMISE 帧,告诉客户端接下来在哪个 Stream 发送资源,然后用偶数号 Stream 发送资源给客户端。
2. HTTP3 vs HTTP2
HTTP2是基于TCP进行传输的,但是基于TCP具有以下局限性:
TCP队头阻塞:TCP要保证数据包按序到达给到应用层,因此可能会出现一个报文stream的帧都到达了,要是等待前面丢失的重传,没办法给到应用层读取。
连接握手延迟与连接迁移: HTTPS 请求前需要经过 TCP 三次握手和 TLS 四次握手(TLS 1.2)建立连接,并且用户IP地址变动时又要重新建立连接,比如手机在4G网络和WiFi之间切换时。
慢启动:发送速率先要有个慢启动的过程。
HTTP3基于QUIC协议,其传输层为UDP:
无队头阻塞:UDP不关心数据包顺序,一个报文的帧都到达后由QUIC协议组装给应用层,丢失了由QUIC协议控制重传。
更快的连接握手与连接迁移:QUIC 协议握手,这个握手过程只需要 1 RTT,握手的目的是为确认双方的「连接 ID」。QUIC 协议的通信双方连接关系就是基于这个连接 ID确定的,而不是IP端口四元组,因此在用户网络发生变化时仍然可以基于连接 ID 继续通信,无需重新建立连接。
二、HTTP报文格式
作为一种应用层协议,其规定的信息交换格式如下:
1. 请求报文
请求报文为主动发送一个http请求的报文,格式说明:
1)请求行(request line):包括请求方法,资源的URL,以及HTTP协议版本。
2)请求头(header):包括请求服务器所需要的附加信息。
3)空行(CRLF):请求头部后面必须是空行,即使请求数据为空,也要有空行。
4)请求数据(body):也称为请求体,可以添加任意类型的数据,通过请求头中的Content-Length字段确定请求数据的长度。
(1)GET请求报文
根据RFC规范,GET 的语义是从服务器获取指定的资源。GET请求一般不携带请求体,如果有请求参数则放在URL后面,一个GET请求报文的样例如下:
GET /video1?p=2 HTTP/1.1 # 请求行:GET请求方式 请求资源路径 HTTP协议版本
Host: www.bilibili.com # 服务器的主机地址和端口号,默认是80
Connection: keep-alive # 和服务端保持长连接
Upgrade-Insecure-Requests: 1 # 让浏览器升级不安全请求,使用https请求
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 # 用户代理,也就是客户端的名称
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 # 可接受的数据类型
Accept-Encoding: gzip, deflate # 可接受的压缩格式
Accept-Language: zh-CN,zh;q=0.9 #可接受的语言
Cookie: pgv_pvi=1246921728; # 登录用户的身份标识
---- 空行 ----
(2)POST请求报文
根据 RFC 规范,POST 的语义是根据请求体(报文body)对指定的资源请求做出处理。一般提交表单时就会使用POST请求,例如登录,一个POST请求报文的样例如下:
POST /login HTTP/1.1 # 请求行:POST请求方式 请求资源路径 HTTP协议版本
Host: www.bilibili.com # 服务器的主机地址和端口号,默认是80
Connection: keep-alive # 和服务端保持长连接
Content-Type: application/json;charset=utf-8 # 请求体的数据类型
Content-Length:32 # 请求体的数据长度
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 # 客户端的名称
---- 空行 ----
{username:hello,pass:123456} # 请求体
2. 响应报文
响应报文为响应一个http请求的报文,格式说明:
状态行(status line): 包括HTTP协议版本,状态码和状态消息
消息报头(header): 包括返回客户端的一些附加信息
空行(CRLF): 必须有空行
响应正文(body): 服务器返回给客户端的数据,可以是任意类型的数据
响应报文样例:
HTTP常见响应状态码
状态码301和302的区别
301是永久重定向,浏览器会缓存请求,之后再请求都是直接到重定向后的地址
302是临时重定向,例如想访问某个资源,但是服务器检测到还未登录,于是302重定向到登录页面
三、HTTP 与 HTTPS的区别
HTTP是明文传输,HTTPS比HTTP多一层SSL/TLS 安全协议,在TCP的三次握手之后,还需进行TLS握手,握手成功后通过秘钥对整个HTTP报文通过对称加密进行密文传输通信。
HTTP 默认端口号是 80,HTTPS 默认端口号是 443。
SSL/TLS 协议基本流程:
客户端向服务器索要并验证服务器的公钥。
双方协商生产「会话秘钥」。
双方采用「会话秘钥」进行加密通信。
前两步就是 TLS 握手阶段,握手过程中的密钥交换算法有两种:RSA 算法 和 ECDHE 算法。
1. 基于RSA的TLS握手机制
(1)第一次握手:客户端首先会发一个「Client Hello」消息,其中包括客户端使用的 TLS 版本号、支持的密码套件列表、以及生成的第一个随机数(Client Random)。
(2)第二次握手:当服务端收到客户端的「Client Hello」消息后,会确认 TLS 版本号是否支持,和从密码套件列表中选择一个密码套件,以及生成第二个随机数(Server Random)。接着返回「Server Hello」消息,其中包括确认 的TLS 版本号、选择的密码套件、Server Random。然后,服务端为了证明自己的身份,会发送「Server Certificate」给客户端,这个消息里含有数字证书。随后,服务端发了「Server Hello Done」消息,目的是告诉客户端,我已经把该给你的东西都给你了,第二次握手完毕。
密码套件基本的形式是「密钥交换算法 + 签名算法 + 对称加密算法 + 摘要算法」
(3)第三次握手:客户端首先对证书进行验证,认为可信则继续往下走。接着客户端就会生成第三个随机数 (pre-master),用服务器公钥加密后传给服务端。然后客户端用这三个随机数生成一个会话秘钥,用于后续通信的对称加密。生成完「会话密钥」后,然后客户端发一个「Change Cipher Spec」,告诉服务端开始使用加密方式发送消息。然后,客户端再发一个「Encrypted Handshake Message(Finished)」消息,把之前所有发送的数据做个摘要,再用会话密钥(master secret)加密一下,让服务器做个验证,验证加密通信「是否可用」和「之前握手信息是否有被中途篡改过」。
数字证书的签发与验证:
(4)第四次握手:服务端收到加密后的第三个随机数 (pre-master)后,用服务端私钥进行解密,然后进行与客户端同样的操作:用这三个随机数生成同样的会话秘钥、发送「Change Cipher Spec」、发送会话秘钥加密后的摘要信息「Encrypted Handshake Message(Finished)」。验证过摘要信息之后客户端和服务端就可以开始用会话秘钥加密通信了。
2. 基于ECDHE的TLS握手机制
使用 RSA 密钥协商算法的最大问题是不支持前向保密。
因为客户端传递随机数(用于生成对称加密密钥的条件之一)给服务端时使用的是公钥加密的,服务端收到后,会用私钥解密得到随机数。所以一旦服务端的私钥泄漏了,过去被第三方截获的所有 TLS 通讯密文都会被破解。
为了解决这个问题,后面就出现了 ECDHE 密钥协商算法,我们现在大多数网站使用的正是 ECDHE 密钥协商算法。
帖子还没人回复快来抢沙发