【网络篇】第十五篇——HTTP协议(二)

HTTP的方法

HTTP的状态码

HTTP常见的Header

Cookie和Session

HTTP VS HTTPS

HTTP/1.1,HTTP/2,HTTP/3演变


前面一章初步认识了URL,HTTP请求和相应协议格式,有所忘记的可以看一下前面的博客

(3条消息) 【网络篇】第十四篇——HTTP协议(一)(附带电视剧李浔同款爱心+端口号被恶意占用如何清除)_接受平凡 努力出众的博客-CSDN博客

HTTP的方法

HTTP常见的方法有:

方法说明支持的HTTP协议版本
GET获取资源1.0,1.1
POST传输实体主体1.0,1.1
PUT传输文件1.0,1.1
HEAD获得报文首部1.0,1.1
DELETE删除文件1.0,1.1
OPTIONS访问支持的方法1.1
TRACE追踪路径1.1
CONNECT要求用隧道协议连接代理1.1
LINK建立和资源之间的联系1.0
UNLINK断开连接关系1.0

其中最常用的就是GET方法和POST方法。

GET方法和POST方法 

GET方法的含义是请求从服务器获取资源, 这个资源可以是文本,页面,图片视频等等。

例如,你打开我在CSDN写的文章,浏览器就会发送GET请求给服务器,服务器就会返回文章的所有文字及资源。

 POST方法则是相反的,一般用于将数据上传给服务器,它向URI指定的资源提交数据,数据就放在报文的body中.

例如,你在我的CSDN文章下面,评论了然后提交,浏览器就会执行一次POST请求,把你的评论放进报文body里,然后拼接好POST请求头,通过TCP协议发送给服务器。

GET方法和POST方法都可以带参:

  • GET方法是通过url传参的。
  • POST方法是通过正文传参的。

从GET方法和POST方法的传参形式可以看出,POST方法能传递更多的参数,因为url的长度是有限制的,而POST方法通过正文传参就可以携带比它更多的数据。

使用POST方法的传参会更加私密,因为POST方法不会将你的参数回显到url当中,此时也就不会被别人轻易看到。不能说POST方法比GET方法更安全,因为POST方法和GET方法实际上都不安全,要做到安全只能通过加密来完成。

GET和POST方法都是安全和幂等的嘛?

先说明下安全和幂等的概念:

  •   HTTP 协议里,所谓的「安全」是指请求方法不会「破坏」服务器上的资源。
  • 所谓的「幂等」,意思是多次执行相同的操作,结果都是「相同」的。
那么很明显 GET 方法就是安全且幂等的 ,因为它是「只读」操作,无论操作多少次,服务器上的数据 都是安全的,且每次的结果都是相同的。 
POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以 不安全 的,且多次提交数据 就会创建多个资源,所以 不是幂等 的。

Postman演示GET和POST区别

 如果访问我们的服务器使用的是GET方法,此时应该通过url进行传参,可以在Params下进行参数设置,因为Postman当中的Params就相当于url当中的参数,你在设置参数时可以看到对应的url也在随之变化。

此时在我们的服务器收到的HTTP请求当中,可以看到请求行中的url就携带上了我们刚才在Postman当中设置的参数。

而如果我们使用的是POST方法,此时就应该通过正文进行传参,可以在Body下进行参数设置,在设置时可以选中Postman当中的raw方式传参,表示原始传参,也就是你输入的参数是什么样的实际传递的参数就是什么样的.

 此时服务器收到的HTTP请求的请求正文就不再是空字符串了,而是我们通过正文传递的参数。

 因为此时响应正文不为空字符串,因此响应报头当中出现了Content-Length属性,表示响应正文的长度。

TCP套接字演示GET和POST的区别

 要演示GET方法和POST方法传参的区别,就需要让浏览器提交参数,此时我们可以在index.html当中再加入两个表单,用作用户名和密码的输入,然后再新增一个提交按钮,此时就可以让浏览器提交参数了。

我们可以通过修改表单当中的method属性指定参数提交的方法,还有一个属性叫做action,表示想把这个表单提交给服务器上的哪个资源。

此时当我们用浏览器访问我们的服务器时,就会显示这两个表单。

当前我们是用GET方法提交参数的,当我们填充完用户名和密码进行提交时,我们的用户名和密码就会自动被同步到url当中。

 同时在服务器这边也通过url收到了刚才我们在浏览器提交的参数。

如果我们将提交表单的方法改为POST方法,此时当我们填充完用户名和密码进行提交时,对应提交的参数就不会在url当中体现出来,而会通过正文将这两个参数传递给了服务器。

 此时用户名和密码就通过正文的形式传递给服务器了。

 说明一下:

  • 使用GET方法时,我们提交的参数会回显到url当中,因此GET方法一般是处理数据不敏感的。
  • 如果你要传递的数据比较私密的话一定要用POST方法,不是因为POST方法安全,实际上GET和POST方法传参都是明文传送,因此都不安全,但是相比于GET而言POST方法更加私密,因为POST是通过正文传参的,不会将参数显示到浏览器上的url框上。

HTTP的状态码

  •  1xx类:属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。
  •  2xx类:表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。

   200 OK]是最常见的成功状态码,表示一切正常。如果是非HEAD请求,服务器返回的响应头都会有body数据。

    204 No Content]也是最常见的成功状态码,也200 OK基本相同,但是响应头没有body数据。

      [206 Partial Contentt]:是应用于HTTP分块下载或断点续传,表示响应返回的body数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态。

  •  3xx类:码表示客户端请求的资源发送了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向
     「 301 Moved Permanently 」表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。
      「 302 Found 」表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。

     

301 302 都会在响应头里使用字段 Location ,指明后续要跳转的 URL ,浏览器会自动重定向新的 URL。
       「 304 Not Modified 」不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,用于缓存控制。
  •  4xx类:表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。
      「 400 Bad Request 」表示客户端请求的报文有错误,但只是个笼统的错误。
      「 403 Forbidden 」表示服务器禁止访问资源,并不是客户端的请求出错。
      404 Not Found 」表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。
  • 5xx类:表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误
    码。
     「 500 Internal Server Error 」与 400 类型,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道。
     「 501 Not Implemented 」表示客户端请求的功能还不支持,类似 即将开业,敬请期待 的意思
     「 502 Bad Gateway 」通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。
     「 503 Service Unavailable 」表示服务器当前很忙,暂时无法响应服务器,类似 网络服务正忙,请稍后重试” 的意思。

 临时重定向演示

进行临时重定向时需要用到Location字段,Location字段是HTTP报头当中的一个属性信息,该字段表明了你所要重定向到的目标网站。

我们这里要演示临时重定向,可以将HTTP响应当中的状态码改为307,然后跟上对应的状态码描述,此外,还需要在HTTP响应报头当中添加Location字段,这个Location后面跟的就是你需要重定向到的网页,比如我们这里将其设置为CSDN的首页。

#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;

int main()
{
	//创建套接字
	int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (listen_sock < 0){
		cerr << "socket error!" << endl;
		return 1;
	}
	//绑定
	struct sockaddr_in local;
	memset(&local, 0, sizeof(local));
	local.sin_family = AF_INET;
	local.sin_port = htons(8081);
	local.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0){
		cerr << "bind error!" << endl;
		return 2;
	}
	//监听
	if (listen(listen_sock, 5) < 0){
		cerr << "listen error!" << endl;
		return 3;
	}
	//启动服务器
	struct sockaddr peer;
	memset(&peer, 0, sizeof(peer));
	socklen_t len = sizeof(peer);
	for (;;){
		int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
		if (sock < 0){
			cerr << "accept error!" << endl;
			continue;
		}
		if (fork() == 0){ //爸爸进程
			close(listen_sock);
			if (fork() > 0){ //爸爸进程
				exit(0);
			}
			//孙子进程
			char buffer[1024];
			recv(sock, buffer, sizeof(buffer), 0); //读取HTTP请求
			cout << "--------------------------http request begin--------------------------" << endl;
			cout << buffer << endl;
			cout << "---------------------------http request end---------------------------" << endl;
			
			//构建HTTP响应
			string status_line = "http/1.1 307 Temporary Redirect\n"; //状态行
			string response_header = "Location: https://www.csdn.net/\n"; //响应报头
			string blank = "\n"; //空行
			string response = status_line + response_header + blank; //响应报文
			
			//响应HTTP请求
			send(sock, response.c_str(), response.size(), 0);

			close(sock);
			exit(0);
		}
		//爷爷进程
		close(sock);
		waitpid(-1, nullptr, 0); //等待爸爸进程
	}
	return 0;
}

如果我们用浏览器访问我们的服务器,当浏览器收到这个HTTP响应后,还会对这个HTTP响应进行分析,当浏览器识别到状态码是307后就会提取出Location后面的网址,然后继续自动对该网站继续发起请求,此时就完成了页面跳转这样的功能,这样就完成了重定向功能。

此时当浏览器访问我们的服务器时,就会立马跳转到CSDN的首页。

HTTP常见的Header

HTTP常见的Header如下:

  • Content-Type:数据类型(text/html等)
  • Content-Length:正文的长度。
  • Host:客户端告知服务器,所请求的资源是在哪个主机的哪个端口上。
  • User-Agent:声明用户的操作系统和浏览器的版本信息。
  • Referer:当前页面是哪个页面跳转过来的。
  • Location:搭配3XX状态码使用,告诉客户端接下来要去哪里访问。
  • Cookie:用于在客户端存储少量信息,通常用于实现会话(session)的功能。

Host:

客户端发送请求时,用来指定服务器的域名。

 

 有了Host字段,就可以将请求发往[同一台]服务器上的不同网站。

Content-Length

服务器在返回数据时,会有Content-Length字段,表明本次回应的数据长度

 如上面则是告诉浏览器,本次服务器回应的数据长度是1000个字节,后面的字节就属于下一个回应了。

Connection

Connection 字段最常用于客户端要求服务器使用 TCP 持久连接,以便其他请求复用。

HTTP/1.1 版本的默认连接都是持久连接,但为了兼容老版本的 HTTP ,需要指定 Connection 首部字段的值为 Keep-Alive

 一个可以复用的 TCP 连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段。 

 User-Agent

User-Agent代表的是客户端对应的操作系统和浏览器的版本信息。

比如当我们用电脑下载某些软件时,它会自动向我们展示与我们操作系统相匹配的版本,这实际就是因为我们在向目标网站发起请求的时候,User-Agent字段当中包含了我们的主机信息,此时该网站就会向你推送相匹配的软件版本。

Content-Type 

Content-Type 字段用于服务器回应时,告诉客户端,本次数据是什么格式。

 

上面的类型表明,发送的是网页,而且编码是UTF-8.

客户端请求的时候,可以使用 Accept 字段声明自己可以接受哪些数据格式。 上面代码中,客户端声明自己可以接受任何格式的数据。

Content-Encoding

 Content-Encoding 字段说明数据的压缩方法。表示服务器返回的数据使用了什么压缩格式

上面表示服务器返回的数据采用了 gzip 方式压缩,告知客户端需要用此方式解压。
客户端在请求时,用 Accept-Encoding 字段说明自己可以接受哪些压缩方法。

Cookie和Session

HTTP实际上是一种无状态协议,HTTP的每次请求/响应之间是没有任何关系的,但你在使用浏览器的时候发现并不是这样的。

比如你登录一次CSDN侯,就算把CSDN网站关了甚至是重启电脑,当你再次打开CSDN网站时,CSDN并没有要求你再次输入账号和密码,这实际上就是通过cookie技术实现的,点击浏览器当中的锁的标志就可以看到对应网站的各种cookie数据。

 这些cookie数据实际都是对应的服务器方写的,如果你将对应的某些cookie删除,那么此时可能就需要你重新进行登录认证了,因为你删除的可能正好就是你登录时所设置的cookie信息。

cookie是什么

 由于HTTP是一种无状态协议,如果没有cookie的存在,那么每当要进行页面请求时都需要重新输入账号和密码进行认证,这样太麻烦。

例如登录 -> 添加购物车 -> 下单 -> 结算 -> 支付,这系列操作都要知道用户的身份才行。但服务器不知道这些请求是有关联的,每次都要问一遍身份信息。 那么我们就需要有一种独立技术帮助我们支持,这种技术目前已经内置到HTTP协议种,叫做cookie。

当我们第一次登录某个网站时,需要输入我们的账号和密码进行身份认证,此时如果服务器经过数据比对后判定你是一个合法的用户,那么为了让你后续在进行某些网页请求时不用重新输入账号和密码,此时服务器就会进行Set-Cookie的设置。(Set-Cookie也是HTTP报头当中的一种属性信息)
当认证通过并在服务端进行Set-Cookie设置后,服务器在对浏览器进行HTTP响应时就会将这个Set-Cookie响应给浏览器。而浏览器收到响应后会自动提取出Set-Cookie的值,将其保存在浏览器的cookie文件当中,此时就相当于我的账号和密码信息保存在本地浏览器的cookie文件当中。

从第一次登录认证之后,浏览器再向该网站发起HTTP请求当中就就会自动包含一个cookie字段,其中携带的就是我第一次的认证信息,此后对端服务器需要对你进行认证时就会直接提取出HTTP请求当中的cookie字段,而不会重新让你输出账号和密码了。

相当于, 在客户端第一次请求后,服务器会下发一个装有客户信息的「小贴纸」,后续客户端请求服务 器的时候,带上「小贴纸」,服务器就能认得了了

也就是在第一次认证登录后,后续所有的认证都变成了自动认证,这就叫做cookie技术。

内存级别&文件级别 

 cookie就是在浏览器当中的一个小文件,文件里记录就是用户的私有信息,cookie文件可以分种,一种是内存级别的cookie文件,另一种是文件级别的cookie文件。

  • 将浏览器关掉之后再打开,访问之前登录过的网站,如果需要你重新输入账号和密码,说明你之前登录时浏览器当中保存的cookie信息是内存级别的。
  • 将浏览器关掉甚至关机重启再打开,访问之前登录的网站,如果不需要你重新输入账号和密码,说明你之前登录时浏览器当中保存的cookie信息是文件级别的。

cookie被盗取

如果你浏览器当中保存的cookie信息被非法用户盗取了,那么此时这个非法用户就可以用你的cookie信息,以你的身份去访问你曾经访问过的网站,我们将这种现象称为cookie被盗取了。

比如你不小心点了某个链接,这个链接可能就是一个下载程序,当你点击之后它就会通过某种方式把程序下载到你本地,并且自动执行该程序,该程序会扫描你的浏览器当中的cookie目录,把所有的cookie信息通过网络的方式传送给恶意方,当恶意方拿到你的cookie信息后就可以拷贝到它的浏览器对应的cookie目录当中,然后以你的身份访问你曾经访问过的网站。

SessionID

单纯的使用cookie是非常不安全的,因为此时cookie文件当中就保存的是你的私密信息,一旦cookie文件泄漏你的隐私信息也就泄漏。

所以当前主流的服务器还引入了SessionID这样的概念,当我们第一次登录某个网站输入账号和密码后,服务器认证成功后还会服务端生成一个对应的SessionID,这个SessionID与用户信息是不相关的。系统会将所有登录用户的SessionID值统一维护起来。

此时当认证通过后服务端在对浏览器进行HTTP响应时,就会将这个生成的SessionID值响应给浏览器。浏览器收到响应后会自动提取出SessionID的值,将其保存在浏览器的cookie文件当中。后续访问该服务器时,对应的HTTP请求当中就会自动携带上这个SessionID

 而服务器识别到HTTP请求当中包含了SessionID,就会提取出这个SessionID,然后再到对应的集合当中进行对比,对比成功就说明这个用户是曾经登录过的,此时也就自动就认证成功了,然后就会正常处理你发来的请求,这就是我们当前主流的工作方式。

安全是相对的

 引入SessionID之后,浏览器当中的cookie文件保存的是SessionID,此时这个cookie文件同样可能被盗取。此时用户的账号和密码虽然不会泄漏了,但用户对应的SessionID是会泄漏的,非法用户仍然可以盗取我的SessionID去访问我曾经访问过的服务器,相当于还是存在刚才的问题。

  • 之前的工作方式就相当于把账号和密码信息在浏览器当中再保存一份,每次请求时都自动将账号和密码的信息携带上,但是账号和密码一直在网当中发送太不安全了。
  • 因此现在的工作方式是,服务器只有在第一次认证的时候需要在网络中传输账号和密码,此后在网络上发送的都是SessionID。

这种方法虽然没有真正解决安全问题,但这种方法是相对安全的。互联网上是不存在绝对安全这样的概念的,任何安全都是相对的,就算你将发送到网络当中的信息进行加密,也有可能被别人破解。

不过在安全领域有一个准则:如果破解某个信息的成本已经远远大于破解之后获得的收益(说明做这个事是赔本的),那么就可以说这个信息是安全的

引入SessionID后的好处

  • 在引入SessionID之前,用户登录的账号信息都是保存在浏览器内部的,此时的账号信息是由客户端去维护的。
  • 而引入SessionID后,用户登录的账号信息是有服务器去维护的,在浏览器内部保存的只是SessionID。

此时虽然SessionID可能被非法用户盗取,但服务器也可以使用各种各样的策略来保证用户账号的安全。

  • IP是有归类的,可以通过IP地址来判断登录用户所在的地址范围。如果一个账号在短时间内登录地址发送了巨大变化,此时服务器就会立马识别到这个账号发生异常了,进而在服务器当中清除对应的SessionID的值。这时当你或那个非法用户想要访问服务器时,就都需要重新输入账号和密码进行身份认证,而只有你是知道自己的密码的,当你重新认证登录后服务器就可以将另一方识别为非法用户,进而对该非法用户进行对应的黑名单/白名单认证。
  • 当操作者想要进行某些高权限的操作时,会要求操作者再次输入账号和密码信息,再次确认身份。就算你的账号被非法用户盗取了,但非法用户在改你密码时需要输入旧密码,这是非法用户在短时间内无法做到的,因为它并不知道你的密码。这也就是为什么账号被盗后还可以找回来的原因,因为非法用户无法在短时间内修改你的账号密码,此时你就可以通过追回的方式让当前的SessionID失效,让使用该账号的用户进行重新登录认证
  • SessionID也有过期策略,比如SessionID是一个小时内是有效的。所以即便你的SessionID被非法用户盗取了,也仅仅是在一个小时内有效,而且在功能上受约束,所以不会造成太大的影响。

任何事情都有两面性,如果不是这些非法用户的存在,现在的服务器肯定是漏洞百出,只有双方不断进行对抗双方才能不断进步。

HTTP VS HTTPS

HTTP与HTTPS有哪些区别?

1.HTTP是超文本传输协议,信息是明文传输,存在安全风险的问题,HTTPS则解决HTTP不安全的缺陷,在TCP和HTTP网络层之间加入了SSL/TLS安全协议,使得报文能够加密传输。

2. HTTP连接建立相对简单,TCP三次握手后便可以进行HTTP的报文传输。而HTTPS在TCP三次握手之后,还需进行SSL/TLS的握手过程,才可进入加密报文传输。

3.HTTP的端口号是80,HTTPS的端口号是443。

4.HTTPS协议需要向CA申请数字整数,来保证服务器的身份是可信的。

HTTPS解决了HTTP的哪些问题?

HTTP由于是明文传输,所以安全上存在以下三个风险:

  • 窃听风险比如通信链路上可以获取通信内容,用户号容易没。
  • 篡改风险,比如强制植入垃圾广告,视觉污染,用户眼容易瞎。
  • 冒充风险,比如冒充淘宝网站,用户钱容易没。

HTTPS在HTTP与TCP层之间加入了SSL/TLS协议,可以很好的解决了上述的风险:

  • 信息加密:交互信息无法被窃取,但你得号回因为[自身忘记]账号而没。
  • 校验机制:无法篡改通信内容,篡改了就不能正常显示,但百度[竞价排名]依然可以搜索到垃圾广告。
  • 身份证书:证明淘宝是真的淘宝网。

可见,SSL/TLS协议是能保证通信是安全的.

HTTPS是如何解决上面的三个风险的? 

  • 混合加密的方式实现信息的机密性,解决了窃听的风险。 
  • 摘要算法的方式来实现完整性,它能够为数据生成独一无二的[指纹],指纹用于校验数据完整性,解决了篡改的风险。
  • 将服务器公钥放入到数字证书中,解决了冒充的风险。

混合加密

通过混合加密的方式就可以保证信息的机密性,解决了窃听的风险.

HTTPS 采用的是 对称加密 非对称加密 结合的「混合加密」方式
  • 在通信建立前采用 非对称加密 的方式交换「会话秘钥」,后续就不再使用非对称加密。
  • 在通信过程中全部使用 对称加密 的「会话秘钥」的方式加密明文数据

采用「混合加密」的方式的原因:

  •  对称加密只使用一个密钥,运算速度快,密钥必须保密,无法做到安全的密钥交换
  • 非对称加密 使用两个密钥:公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但 速度慢。

摘要算法

摘要算法 用来实现 完整性 ,能够为数据生成独一无二的「指纹」,用于校验数据的完整性,解决了篡改的风险。

 

客户端在发送明文之前会通过摘要算法算出明文的「指纹」,发送的时候把「指纹 + 明文」一同加密成密文后,发送给服务器,服务器解密后,用相同的摘要算法算出发送过来的明文,通过比较客户端携带的「指纹」和当前算出的「指纹」做比较,若「指纹」相同,说明数据是完整的。
数字证书
客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。
这就存在些问题,如何保证公钥不被篡改和信任度? 所以这里就需要借助第三方权威机构 CA (数字证书认证机构),将 服务器公钥放在数字证书 (由数字证书认证机构颁发)中,只要证书是可信的,公钥就是可信的。

通过数字证书的方式保证服务器公钥的身份,解决冒充的风险。

HTTP/1.1,HTTP/2,HTTP/3演变

HTTP/1.1相比 HTTP/1.0提高了什么性能?

HTTP/1.1相比HTTP/1.0性能上的改进:

  • 使用TCP长连接方式改善了HTTP/1.0短链接造成的性能开销。
  • 支持管道(pipeline)网络传输,只要第一个请求发出去了,不必等其回来,就可以发送第二个请求出去,可以减少整体的响应时间。

但HTTP/1.1还是有性能瓶颈:

  • 请求/响应头部(Header)未经压缩就发送,首部信息越多延迟越大。只能压缩Body的部分。
  • 发送冗长的首部。每次互相发送相同的首部造成浪费较多;
  • 服务器是按请求的顺序相应的,如果服务器响应慢,会招致客户端一直请求不到数据,也就是对头阻塞;
  • 没有请求优先级控制;
  • 请求只能从客户端开始,服务器只能被动响应。

那上面的HTTP/1.1的性能瓶颈,HTTP/2做了什么优化? 

HTTP/2 协议是基于 HTTPS 的,所以 HTTP/2 的安全性也是有保障的。
HTTP/2 相比 HTTP/1.1 性能上的改进:
1. 头部压缩
HTTP/2 压缩头 Header )如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会 帮你 消除重复的部分
这就是所谓的 HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表, 生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就 提高速度 了。
2. 二进制格式
HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用了 二进制格式 ,头信息和数据体都是二进制,并且统称为帧(frame ): 头信息帧和数据帧
这样虽然对人不友好,但是对计算机非常友好,因为计算机只懂二进制,那么收到报文后,无需再将明文的报文转成二进制,而是直接解析二进制报文,这 增加了数据传输的效率
3. 数据流
HTTP/2 的数据包不是按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。 每个请求或回应的所有数据包,称为一个数据流( Stream )。每个数据流都标记着一个独一无二的编号,其中规定客户端发出的数据流编号为奇数, 服务器发出的数据流编号为偶数客户端还可以 指定数据流的优先级 。优先级高的请求,服务器就先响应该请求。
4. 多路复用
HTTP/2 是可以在 一个连接中并发多个请求或回应,而不用按照顺序一一对应
移除了 HTTP/1.1 中的串行请求,不需要排队等待,也就不会再出现「队头阻塞」问题, 降低了延迟, 大幅度提高了连接的利用率
举例来说,在一个 TCP 连接里,服务器收到了客户端 A B 的两个请求,如果发现 A 处理过程非常耗 时,于是就回应 A 请求已经处理好的部分,接着回应 B 请求,完成后,再回应 A 请求剩下的部分。
5. 服务器推送
HTTP/2 还在一定程度上改善了传统的「请求 - 应答」工作模式,服务不再是被动地响应,也可以 主动 向客户端发送消息。
举例来说,在浏览器刚请求 HTML 的时候,就提前把可能会用到的 JS CSS 文件等静态资源主动发给客户端, 减少延时的等待 ,也就是服务器推送( Server Push ,也叫 Cache Push )。

HTTP/2有哪些缺陷?HTTP/3做了哪些优化?

HTTP/2 主要的问题在于,多个 HTTP 请求在复用一个 TCP 连接,下层的 TCP 协议是不知道有多少个 HTTP 请求的。所以一旦发生了丢包现象,就会触发 TCP 的重传机制,这样在一个 TCP 连接中的 所有 HTTP 请求都必须等待这个丢了的包被重传回来
  • HTTP/1.1 中的管道( pipeline )传输中如果有一个请求阻塞了,那么队列后请求也统统被阻塞住了
  • HTTP/2 多个请求复用一个 TCP 连接,一旦发生丢包,就会阻塞住所有的 HTTP 请求。
    这都是基于 TCP 传输层的问题,所以 HTTP/3 HTTP 下层的 TCP 协议改成了 UDP

UDP 发生是不管顺序,也不管丢包的,所以不会出现 HTTP/1.1 的队头阻塞 和 HTTP/2 的一个丢包全部重传问题。
大家都知道 UDP 是不可靠传输的,但基于 UDP QUIC 协议 可以实现类似 TCP 的可靠性传输。
  • QUIC 有自己的一套机制可以保证传输的可靠性的。当某个流发生丢包时,只会阻塞这个流, 其他 流不会受到影响
  • TLS3 升级成了最新的 1.3 版本,头部压缩算法也升级成了 QPack 
    HTTPS 要建立一个连接,要花费 6 次交互,先是建立三次握手,然后是 TLS/1.3 的三次握手。QUIC 直接把以往的 TCP TLS/1.3 6 次交互 合并成了 3 次,减少了交互次数

    所以, QUIC 是一个在 UDP 之上的 TCP + TLS + HTTP/2 的多路复用的协议。

 QUIC 是新协议,对于很多网络设备,根本不知道什么是 QUIC,只会当做 UDP,这样会出现新的问题。所以 HTTP/3 现在普及的进度非常的缓慢,不知道未来 UDP 是否能够逆袭 TCP

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

接受平凡 努力出众

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值