当前位置: 首页 > news >正文

HTTP知识速通

一.HTTP的基础概念

首先了解HTTP协议,他是目前主要使用在应用层的一种协议

http被称为超文本传输协议

而https则是安全的超文本传输协议

本章节的内容首先就是对http做一个简单的了解。

HTTP是一种应用层协议,是基于TCP/IP协议来传递信息的。

其中http1.0,http1.1,http2.0均为TCP实现,http3.0则是UDP实现。

说了半天,那啥是协议?

协议其实就是为了使数据在网络上从源头到达目的,网络通信的参与方必须遵循相同的规则,这套规则称为协议。

二.简单的HTTP协议

2.1URI和URL

在学习HTTP协议之前,首先介绍一下URI和URL

URI (统一资源标识符),如下图

URL(统一资源定位符)

其正是使用 Web 浏览器等 访问 Web 页面时需要输入的网页地址

那他们两个有什么区别呢?

  • URI(Uniform Resource Identifier):

是一个广义的资源标识符,唯一标识某个资源(如网页、图片、文件等),不限定标识方式。

  • URL(Uniform Resource Locator):

是URI的子集,不仅标识资源,还提供具体的访问方式(如协议、路径、服务器地址等)

也就是说url是uri的一种表示方式。

可能这样说还是有点迷糊,那我就举一个更为简单的例子吧

URI = 资源唯一标识

(如身份证号,唯一但无法直接定位)

URL = 资源唯一标识 + 定位方法

(如家庭住址,既能标识也能找到置)

换句话说URI只能标记它是一个资源,但是无法判断他在哪里,而URL不仅是资源还能定位

常见的uri还有邮箱(邮箱可以标识一个资源)

简言之:URL是URI的一种具体实现,用于定位资源;URI更通用,仅需标识资源。

2.2 HTTP工作过程

再有了上面的了解之后,俺们就要正式的迈入http的介绍了。

既然http是一种协议,或者说一种规矩,那他是如何工作的呢?

让我们接着往下看👀

当我们在浏览器输入一个网址,此时浏览器就会给对应的服务器发送一个 HTTP 请求,对应的服务器收到这个请求之后,经过计算处理,就会返回一个 HTTP 响应。

并且当我们访问一个网站时,可能涉及不止一次的 HTTP 请求和响应的交互过程。

这个过程的规定其实就是http协议,按照协议规定的格式进行信息传递。

基础术语:

  • 客户端: 主动发起网络请求的一端
  • 服务器: 被动接收网络请求的一端
  • 请求: 客户端给服务器发送的数据
  • 响应: 服务器给客户端返回的数据

2.3 http的特点

上述所说的请求和响应,其实也是http的特点,但他的特点远不如此。

注⚠️ :网络编程中,并不只有一发一收的形式,还有一对多,多对多的形式。

先来说一下http的优点吧:简单,灵活和易于拓展,应用广泛和跨平台

  1. 简单就是指他的报文格式 header + body,头部信息也是 key-value 简单文本的形式
  2. 灵活和易于拓展就是指他协议里面的请求方法,uri/url,状态码等没有被固定死,允许开发人员自定义和扩充
  3. 应用广泛和跨平台,就是指的台式的浏览器到手机上的各种APP都是

当然不仅仅有优点,也有缺点(虽然说是缺点,其实就是http的一种特色)

http是一种无状态,明文传输的协议,是不安全的

所谓的无状态,其实就是没有标识。

在第一次发送之后,如果再次由同一个客户端发送请求,虽然两者建立了链接,但仍旧会导致不知道谁发送的请求,因为没有对第一次访问的客户端做身份记录📝

举个例子:

例如在登录->添加购物车->下单->结算->支付,这系列操作都要知道用户的身份才行,但是服务器并不知道这些操作是关联的,就需要每一次都问一遍发信息的人的身份。

每一次的操作都要验证消息,这样的购物还舒服吗?别问,问就是酸爽!

明文传输就是字面意思,不加密,直接把原文发过去,可以直接肉眼查看,为调试工作带来了极大的方便

显然这样的做法肯定都是有问题的,那她不就是相当于信息裸奔吗,暴露在了光天化日之下。

万一里面有你的账号和密码,那.........

2.4 http的问题解决

在了解了http的无状态之后,我们会发现如果没状态岂不是每一次都要做一次身份认证,那岂不是太麻烦了,每次访问一个页面就要重新登陆一次。

为了解决这个问题于是乎就引入了cookie的概念,也就是身份记录。

Cookie技术通过在请求和响应报文中写入Cookie的信息来控制客户端的状态

Cookie会根据从服务器端发送的响应报文中的一个叫做Set-Cookie的首部字段信息,通知客户端保存Cookie,当下一次客户端在往服务器发送请求的时候,客户端会自动在请求报文中加入cookie值,在发送出去

服务端发现客户端发送过来的Cookie后,会去检查到底是哪一个客户端发来的连接请求,然后对比服务器上的记录最后得到之前的状态。

为了解决明文传输问题和不安全,引入https。

https的内容会在后续介绍

3.HTTPS篇,也可以先去看一下https

三.HTTP的缓存技术

在之前的学习中我们会发现,如果每一次访问,都需要去服务端查找所需要的资源,如果我发送同样的求,那又需要建立连接,又要去服务端下面去查找内容,那这样岂不是很浪费嘛?

那有没有什么好的办法可以解决重复性请求的问题呢?

当然是有的,http协议通过引入缓存技术,从而解决这个问题

HTTP的缓存实现主要有两种方式,分别是强制缓存和协商缓存

3.1强制缓存

强制缓存指的是只要浏览器判断缓存没有过期,则直接使用浏览器的本地缓存,决定是否使用缓存的主动性在于浏览器这边。

如下图中,返回的是 200 状态码,但在 size 项中标识的是 from disk cache就是使用了强制缓存。

强制缓存是利用HTTP响应中的两个字段实现的,他们都标识资源在客户端缓存的有效期:

  • Cache-Control, 是一个相对时间;
  • Expires,是一个绝对时间;

如果 HTTP 响应头部同时有 Cache-Control 和 Expires 字段的话,Cache-Control 的优先级高于 Expires 。

Cache-control 选项更多一些,设置更加精细,所以建议使用Cache-Control 来实现强缓存。具体的实现流程如下:

  • 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时在 Response 头部加上 Cache-Control,Cache-Control 中设置了过期时间大小;
  • 浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使用该缓存,否则重新请求服务器;
  • 服务器再次收到请求后,会再次更新 Response 头部的 Cache-Control。

也就是在客户端将这些资源存储到了浏览器的缓存之中,当需要的再次访问的时候,会先查询本地缓存是否过期,如果过期则重新申请资源

3.2 协商缓存

但是强制缓存也会带来一个问题就是,如果在这段未过期时间内,如果请求资源的内容发生了改变,那在看旧版的岂不是不太好?

别担心,设计者也考虑到了这个问题(在这里之前可以先去看一下响应的状态码,4.2.1下面的内容)

于是乎就有了协商缓存这个东西。

当我们在浏览器使用开发者工具的时候,你可能会看到过某些请求的响应码是304,这个是告诉浏览器可以使用本地缓存的资源,通常这种通过服务端告知客户端是否可以使用缓存的方式被称为协商缓存。

上面就是一个协商缓存的过程,所谓的协商其实就是判断要不要用本地缓存,那这个判断条件就是我们之前所说的----这个资源有没有被更新

协商缓存可以基于两种头部来实现,有两种不同的方式

  • 第一种:请求头部中的 If-Modified-Since 字段与响应头部中的Last-Modified 字段实现

  • 第二种:请求头部中的 If-None-Match 字段与响应头部中的 ETag 字段

那他们的区别又是什么呢?

其实看完这些字段,就能知道,第一种方式是基于时间实现的,第二种则是基于一个唯一标识

前者会出现时间回溯或者被篡改等问题,所以一般都是采用后者(除此之外还可以解决其他比如Etag可以解决1s内多次刷新的操作等等)

这里需要注意一点:协商缓存这两个字段都需要配合强制缓存中 Cache-Control 字段来使用只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求

下面是一个强制缓存和协商缓存的工作流程

简单说一下采用Etag字段实现的协商缓存的流程:

  • 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 ETag 唯一标识这个唯一标识的值是根据当前请求的资源生成的;

  • 当浏览器再次请求访问服务器中的该资源时,首先会先检查强制缓存是否过期:
    • 如果没有过期,则直接使用本地缓存;
    • 如果缓存过期了,会在 Request 头部加上 If-None-Match 字段,该字段的值就是 ETag 唯一标识;

  • 服务器再次收到请求后,会根据请求中的 If-None-Match 值与当前请求的资源生成的唯一标识进行比较
    • 如果值相等,则返回 304 Not Modified,不会返回资源
    • 如果不相等,则返回 200 状态码和返回资源,并在 Response 头部加上新的ETag 唯一标识;

  • 如果浏览器收到 304 的请求响应状态码,则会从本地缓存中加载资源,否则更新资源。

四.HTTP报文

在经过上面的学习之后,我想对http已经有了一些认识吧,接下来,就让我们深入了解一下http报文,他到底是如何规范网络传输的。

下面是报文的样子。

  • 请求报文

  • 响应报文

这就是http协议的请求和响应的整体结构。下面就会围绕这些内容展开。

4.1 http请求(Request)

4.1.1 认识URL

在之前曾说过URL和URI,在浏览器上,我们大多数是通过URL直接访问数据。

在学习请求之前,要对URL有一个最为基础的了解。

其实访问一个网站,就是访问这个网站对应服务器内的文件资源。

通过这个构成也不难发现。

但是实际上URL有些字段是可以不写的,就比如登入信息,常见的形式就是协议名+服务器地址(也就是域名)

既然说到URL,有时候我们会发现为什么有的URL后面有一堆百分号以及一些乱七八糟的东西,这些东西又是干什么的?

接下来就来介绍一下

GET https://www.sogou.com/web?query=%E8%9B%8B%E7%B3%95&_asf=www.sogou.com&_ast=&w=01019900&p=40040100&ie=utf8&from=index-nologin&s_from=index&sut=1129&sst0=1646360982664&lkt=0%2C0%2C0&sugsuv=003B56A6DA4C2A82610BB3A8CFD5D583&sugtime=1646360982664 HTTP/1.1

这个URL就是一个搜索蛋糕的URL

我们会发现 query string 的有些值是 %E8%9B%8B%E7%B3%950%2C0%2C0

通过 urlencode,知道 %E8%9B%8B%E7%B3%95 就是表示蛋糕

其实也就是所谓的url编码

需要 urlencode 的原因:

  • 这是因为像 /、?、: 等这样的字符,已经被 url 当做特殊意义理解了,因此这些字符不能随意出现。如果某个参数中需要带有这些特殊字符,就必须先对特殊字符进行转义,即 urlencode
  • 一个中文字符由 UTF-8 或者 GBK 这样的编码方式构成,虽然在 URL 中没有特殊含义,但是仍然需要进行转义,否则浏览器可能把 UTF-8/GBK 编码中的某个字节当做 URL 中的特殊符号

其次还有查询参数,也就是在URL 中的 `?query=`、`?key=value` 这类结构是 URL 查询参数(Query Parameters),它们的作用是向服务器传递额外的信息,通常用于动态网页或接口请求中。

也就是在服务器中的后端代码来提起url中这些查询参数的内容。

如果有多个查询参数,则通过&链接

4.1.2 认识方法(methed)

想必大家肯定都听说什么get,post方法,那他们到底是干什么的,有什么区别?

这里知道的同学可以先跳过😊

主要介绍一下GET请求和POST请求

根据 RFC 规范,GET 的语义是从服务器获取指定的资源

POST 的语义是根据请求负荷(报文body)对指定的资源做出处理

其实也没啥好说的,总结下来就是GET请求时获取定位资源,而POST请求则是对资源做出处理

其实主要要了解的一个问题就是-----GET和POST都是安全幂等的嘛?

首先说一下什么是安全和幂等:

  • 在 HTTP 协议里,所谓的「安全」是指请求方法不会「破坏」服务器上的资源。
  • 所谓的「幂等」,意思是多次执行相同的操作,结果都是「相同」的。

如果从 RFC 规范定义的语义来看:

  • GET 方法就是安全且幂等的,因为它是「只读」操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。所以,可以对 GET 请求的数据做缓存,这个缓存可以做到浏览器本身上(彻底避免浏览器发请求),也可以做到代理上(如nginx),而且在浏览器中 GET 请求可以保存为书签
  • POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的。所以,浏览器一般不会缓存 POST 请求,也不能把 POST 请求保存为书签

做个简要的小结:

GET 的语义是请求获取指定的资源。GET 方法是安全、幂等、可被缓存的。

POST 的语义是根据请求负荷(报文主体)对指定的资源做出处理,具体的处理方式视资源类型而不同。POST 不安全,不幂等,(大部分实现)不可缓存。

注意, 上面是从 RFC 规范定义的语义来分析的。但是实际过程中,开发者不一定会按照 RFC 规范定义的语义来实现 GET 和 POST 方法。

比如:

  • 可以用 GET 方法实现新增或删除数据的请求,这样实现的 GET 方法自然就不是安全和幂等
  • 可以用 POST 方法实现查询数据的请求,这样实现的 POST 方法自然就是安全和幂等。

GET方法也是可以带上body,并且GET的查询参数也不是独有的,,其他比如POST请求也可以有参数

4.1.3 认识请求报头(header)

这个应该就能很好理解,其实所谓的请求报头就是附带的信息,用来描述这个请求。

接下来就简单介绍一下这些键值对的作用,下面的是比较常见的

通用首部字段

先介绍一下通用的首部字段:通用就是指在请求和响应中双方都会使用到的字段

  1. Cache-Control:之前在强制缓存那边涉及过,就是操作缓存的工作机制
  2. Connection:Connection 字段可用于管理持久连接(也称为长连接)。持久连接允许客户端和服务器在请求/响应完成后不立即关闭 TCP 连接,以便在同一个连接上发送多个请求和接收多个响应。在 HTTP/1.1 协议中,默认使用持久连接。当客户端和服务器都不明确指定关闭连接时,连接将保持打开状态,以便后续的请求和响应可以复用同一个连接。在 HTTP/1.0 协议中,默认连接是非持久的。如果希望在 HTTP/1.0上实现持久连接,需要在请求头中显式设置 Connection: keep-alive。keep-alive:表示希望保持连接以复用 TCP 连接。close:表示请求/响应完成后,应该关闭 TCP 连接。
  3. Date:表示HTTP报文的日期和时间
  4. Pragma:是http1.1之前版本的历史遗留字段,仅作为与http/1.0的向后兼容而定义
  5. Transfer-Encoding:规定了传输报文主体时采用的编码方式。
  6. .......(还有几个,个人感觉到时候下去了解一下就行)

请求首部字段

上面简单介绍了一下常见的通用字段,接下来介绍一下request的请求报文的首部字段

Accept 用户代理可处理的媒体类型
Accept-Charset 优先的字符集
Accept-Encoding 优先的内容编码
Accept-Language 优先的语言(自然语言)
Authorization Web认证信息
Expect 期待服务器的特定行为
From 用户的电子邮箱地址
Host 请求资源所在服务器
If-Match 比较实体标记(ETag)
If-Modified-Since 比较资源的更新时间
If-None-Match 比较实体标记(与 If-Match 相反)
If-Range 资源未更新时发送实体 Byte 的范围请求
If-Unmodified-Since 比较资源的更新时间(与If-Modified-Since相反)
Max-Forwards 最大传输逐跳数
Proxy-Authorization 代理服务器要求客户端的认证信息
Range 实体的字节范围请求
Referer 对请求中 URI 的原始获取方
TE 传输编码的优先级
User-Agent HTTP 客户端程序的信息

实体首部字段

Allow 资源可支持的HTTP方法
Content-Encoding 实体主体适用的编码方式
Content-Language 实体主体的自然语言
Content-Length 实体主体的大小(单位:字节)
Content-Location 替代对应资源的URI
Content-MD5 实体主体的报文摘要
Content-Range 实体主体的位置范围
Content-Type 实体主体的媒体类型
Expires 实体主体过期的日期时间
Last-Modified 资源的最后修改日期时间

这里涉及了长连接的问题,对他做出一个解释 : 在进行http传输之前首先要进行tcp的三次握手,建立之后才可以发送http报文,但是每一次发送完报文,它就会自动断开tcp链接,导致每一次发送请求都需要建立连接,造成了很大的开销,所以后续的版本里就引入了长连接,不会导致每次请求都需要建立和断开连接。

这就是http请求报文的一个形式,他里面还有很多的参数,了解就行了,如果需要设置,通过对应语言的请求和响应结构体设置即可。

4.2 http响应(response)

4.2.1 状态码(status code)

状态码表示访问一个页面的结果(如访问成功、失败,还是其它一些情况等等),它是一个3位的整数,从 1xx、2xx、3xx、4xx、5xx,分为五个大类,每个大类的含义都不同。以下介绍一些常见的状态码及它的状态码解释

  • 1xx 状态码

属于信息性状态码,表示服务器已收到请求,需要客户端继续操作或等待进一步处理。它们通常用于临时响应,不会作为最终结果。

(这一块了解就行)

  • 2xx 状态码

基本上200就是表示成功,这是最常见的。

  • 3xx 状态码

301表示永久重定向

302表示临时重定向

(重定向相当于手机呼号的呼叫转移功能,如果我们换了一个手机号,就可以去办理该呼叫转移业务,使朋友拨打你的旧号码时,自动跳转到新号码)

304 表示可以调用本地缓存

  • 4xx

404 notfound 即你发送的url请求在服务器上找不到

403 表示访问被拒绝

405 表示你访问的服务器不支持请求中的方法

  • 5xx

500 表示服务器内部错误

504 表示当前服务器负载比较大,服务器处理单条请求的时耗很长,就会出现超时情况。

这里可能就会有同学有问题了,不是说http是无状态的吗,那为啥还要搞状态码呢?

这里明显就是对这个无状态的认识有点不太深入,这里的无状态是指浏览器不会保存客户端之前的请求。

而状态码则是描述单个请求的结果,换句话说也就是返回服务器当前的状态,所以并没有改变无状态的本质。

4.2.2 认识响应报头

响应报头其实和请求报头差不多,接下来简单介绍一下:

他的结构也是三部分,只不过就是将请求首部字段换成响应首部字段,其他方面都是一样的

响应首部字段

Accept-Ranges 是否接受字节范围请求
Age 推算资源创建经过时间
ETag 资源的匹配信息
Location 令客户端重定向至指定URI
Proxy-Authenticate 代理服务器对客户端的认证信息
Retry-After 对再次发起请求的时机要求
Server HTTP 服务器的安装信息
Vary 代理服务器缓存的管理信息
WWW-Authenticate 服务器对客户端的认证信息

五.HTTP的不同版本

HTTP从1.0-到HTTP1.1, HTTP2.0 , HTTP3.0这个演变,都有什么方面的改变?

目前常用的http协议是1.1,但是2.0和3.0的趋势也任然在上升。

5.1 HTTP1.0和1.1相比,提高了什么性能

HTTP1.0和HTTP1.1相比

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

(什么是长连接,其实1.0版本中,每一次发送请求都需要建立连接,响应之后自动断开,所谓的长连接,就是不会自断断开,不用每一次发请求都要建立连接)

虽然1.1版本改进了不少,但是仍旧存在性能瓶颈问题:

  • 请求 / 响应头部(Header)未经压缩就发送,首部信息越多延迟越大,只能压缩 Body 的部分。
  • 发送冗长的首部。每次互相发送相同的首部造成的浪费较多
  • 虽然解决了请求的拥挤,但是如果响应但服务端的响应也是依次的,会导致队头阻塞的问题(说白了就是第一个响应没发出去,后面的响应都发不出去)
  • 没有请求优先控制
  • 请求只能从客户端开始,服务器只能被动响应。

5.2 HTTP/2 做了什么优化?

5.2.1 http2的优改进

首先要知道HTTP/2是基于HTTPS的,所以安全性是有保障的。

接下来看一张图( ﹡ˆoˆ﹡ )

在1.1上的改进

  • 头部压缩
  • 二进制格式
  • 并发传输
  • 服务器主动推送资源

1.头部压缩

HTTP/2 会压缩头(Header)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分。

这就是所谓的 HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。

2.二进制格式

HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧(Headers Frame)和数据帧(Data Frame)

这样做就不需要再将明文转化为二进制了,还增加了传输效率。

这个主要和编码有关,就不过多介绍了,感兴趣可以自行了解₍˄·͈༝·͈˄*₎◞ ̑̑

3.并发传输

我们都知道HTTP/1.1是基于请求响应模型,也就是完成了这样一个请求响应的事务之后,才会处理下一个事务。

这样就会导致你在发送完一个请求,就会进入等待,但是后面还有请求,由于你队头在等待,就会导致后面的请求也进入等待,也就是造成了队头阻塞的问题。

而HTTP2就很牛逼了,引出来stream的概念,多个stream复用一个tcp连接

其实也就是并发的发送数据,这些数据都是一个个的帧(frame),

这里就会想他们都是帧,咋区分哪几个帧是一个数据拆分的啊?

针对这个问题,采用了独一无二的 Stream ID 来区分,接收端可以通过 Stream ID 有序组装成 HTTP 消息,不同 Stream 的帧是可以乱序发送的,因此可以并发不同的 Stream ,也就是 HTTP/2 可以并行交错地发送请求和响应。如下图所示

4.服务器推送

也就是改变了传统的请求响应模式,服务端也可以主动发请求。

客户端和服务器双方都可以建立 Stream,但Stream ID 也是有区别的,客户端建立的 Stream 必须是奇数号而服务器建立的 Stream 必须是偶数号。

知道这些内容就行了,举一个简单的例子:

下面这张图的请求部分可以看见stream4,这个其实就是服务端主动向客户端推送的。

5.2.2 http2点缺陷

虽然http2看似解决了队头阻塞的问题,其实并没有,只不过问题不出在http,而是在tcp上。在文章的开头说过http2是基于tcp的。

那为什么这样做会导致tcp队头阻塞呢?

TCP是基于字节流的协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给 HTTP 应用。那么当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据,这就是 HTTP/2 队头阻塞问题。

这样解释可能比较含糊,我说的简单一点:再此之前,我们要知道一点那就是tcp是可靠的,准确的。正是因为如此,如果说中间传输的过程中,如果一个帧丢失了,也就是所谓的丢包了,就会导致tcp重传,只有这个包被重新传入,其它的http请求才会正常工作。

5.3 HTTP/3又有什么优化呢?

首先就是HTTP/1.1和HTTP/2都存在队头阻塞的问题。

1.1是通过管道解决了请求队头阻塞,但是没有解决响应的队头阻塞

2通过多个请求复用一个tcp连接,解决了http的队头阻塞,但是一旦丢包就会导致tcp层队头阻塞。

HTTP/2队头阻塞的问题是由tcp导致的,所以HTTP/3就把他换成了UDP

UDP 发送是不管顺序,也不管丢包的,所以不会出现像 HTTP/2 队头阻塞的问题。大家都知道 UDP 是不可靠传输的,但基于 UDP 的 QUIC 协议 可以实现类似 TCP 的可靠性传输。

QUIC主要有三个特点:

  • 无队头阻塞
  • 更快的连接建立
  • 连接迁移

1.无队头阻塞

QUIC 协议也有类似 HTTP/2 Stream 与多路复用的概念,也是可以在同一条连接上并发传输多个 Stream,Stream 可以认为就是一条 HTTP 请求。

他有自己的一套机制可以保证传输的可靠性的。当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响,因此不存在队头阻塞问题。这与 HTTP/2 不同,HTTP/2 只要某个流中的数据包丢失了,其他流也会因此受影响。

也就是QUIC 连接上的多个 Stream 之间并没有依赖,都是独立的,某个流发生丢包了,只会影响该流,其他流不受影响。

2.更快的连接建立

对于 HTTP/1 和 HTTP/2 协议,TCP 和 TLS 是分层的,分别属于内核实现的传输层,openssl 库实现的表示层,因此它们难以合并在一起,需要分批次来握手,先 TCP 握手,再 TLS 握手。

HTTP/3 在传输数据前虽然需要 QUIC 协议握手,但是这个握手过程只需要 1 RTT,握手的目的是为确认双方的「连接 ID」,连接迁移就是基于连接 ID 实现的。

但是 HTTP/3 的 QUIC 协议并不是与 TLS 分层,而是 QUIC 内部包含了 TLS,它在自己的帧会携带 TLS 里的“记录”,再加上 QUIC 使用的是 TLS/1.3,因此仅需 1 个 RTT 就可以「同时」完成建立连接与密钥协商。

(RTT : 数据从发送端到接收端再返回发送端所需的时间)

甚至,在第二次连接的时候,应用数据包可以和 QUIC 握手信息(连接信息 + TLS 信息)一起发送,达到 0-RTT 的效果。

3.连接迁移

基于 TCP 传输协议的 HTTP 协议,由于是通过四元组(源 IP、源端口、目的 IP、目的端口)确定一条 TCP 连接。

那么当移动设备的网络从4G切换到WIFI时,意味着IP地址变化了,那么就必须要断开连接,然后重新建立连接。而建立连接的过程包含TCP三次握手和TLS 四次握手的时延,以及TCP慢启动的减速过程,给用户的感觉就是网络突然卡顿了一下,因此连接的迁移成本是很高的。

而QUIC协议没有用四元组的方式来“绑定”连接,而是通过连接ID来标记通信的两个端点,客户端和服务器可以各自选择一组ID来标记自己,因此即使移动设备的网络变化后,导致IP地址变化了,只要仍保有上下文信息(比如连接ID.TLS密钥等),就可以“无缝”地复用原连接,消除重连的成本,没有丝毫卡顿感,达到了连接迁移的功能。

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

QUlC是新协议,对于很多网络设备,根本不知道什么是QUIC,只会当做UDP,这样会出现新的问题,因为有的网络设备是会丢掉UDP包的,而QUIC是基于uDP实现的,那么如果网络设备无法识别这个是QUIC包,那么就会当作UDP包,然后被丢弃。

HTTP/3现在普及的进度非常的缓慢,不知道未来UDP是否能够逆袭TCP.

相关文章:

HTTP知识速通

一.HTTP的基础概念 首先了解HTTP协议,他是目前主要使用在应用层的一种协议 http被称为超文本传输协议 而https则是安全的超文本传输协议 本章节的内容首先就是对http做一个简单的了解。 HTTP是一种应用层协议,是基于TCP/IP协议来传递信息的。 其中…...

npm命令介绍(Node Package Manager)

文章目录 npm命令全解析简介基础命令安装npm(npm -v检插版本)初始化项目(npm init)安装依赖包(npm install xxx、npm i xxx) 依赖管理精解依赖类型区分(生产环境依赖dependencies、开发环境依赖…...

在 Windows 上启用 Telnet 命令

在 Windows 上启用打开 Telnet 命令 Telnet 是一种用于远程访问和管理计算机的协议。尽管存在安全漏洞,Telnet 仍然被广泛用于初始网络硬件配置、远程访问、端口测试等任务。在 Windows 10 和 11 上,可以通过多种方法启用 Telnet 客户端。 使用控制面板…...

网络安全零基础培训 L1-9 PHP连接MySQL数据库

使用MySQLi扩展 MySQLi 是 “MySQL Improved Extension” 的缩写&#xff0c;它是 PHP 用于与 MySQL 数据库进行交互的扩展。 step1&#xff1a;连接数据库 <?php// 定义数据库服务器的地址&#xff0c;通常 localhost 表示本地服务器$servername "服务器地址&quo…...

Python生活手册-文件二进制:从快递柜到生鲜冷链的数据保鲜术

一、快递柜与冷链运输&#xff1a;两种存取哲学 1. 普通快递柜&#xff08;文本模式&#xff09; 日常存取包裹的智能快递柜就像文本模式&#xff0c;系统会自动处理包裹的包装&#xff1a; with open(快递单.txt, r, encodingutf-8) as 快递柜:包裹内容 快递柜.read() # …...

CUDA从入门到放弃

1 CUDA简介 GPU为图形处理器, 也是显卡的“大脑”显卡集成了GPU, 显存和其他电路的硬件GPU: 计算密集型CPU: 逻辑流控制GPU性能指标: 核心数GPU显存容量GPU计算峰值显存带宽 GPU不能单独计算, CPUGPU组成异构计算架构CPU起到控制作用, 一般成为主机(Host), GPU可以看作CPU的协…...

Golang多人在线坦克对战游戏(帧同步)

以下是一个简化但完整的同步帧游戏示例——实现一个多人在线坦克对战游戏。代码分为服务器和客户端两部分,使用UDP协议通信。我们将重点讲解核心同步机制。 项目结构 sync-frame-game/ ├── server/ │ ├── main.go # 游戏服务器主逻辑 │ └── game_stat…...

MySQL | DQL语句-连接查询

MySQL | DQL语句-连接查询 &#x1fa84;个人博客&#xff1a;https://vite.xingji.fun 什么是连接查询 从一张表中查询数据称为单表查询。从两张或更多张表中联合查询数据称为多表查询&#xff0c;又叫做连接查询。什么时候需要使用连接查询&#xff1f; 比如这样的需求&…...

JVM——Java 虚拟机是如何加载 Java 类的?

引入 在 Java 世界的底层运作中&#xff0c;类加载机制扮演着一个既神秘又关键的角色。它就像是一个精心设计的舞台幕后 machinery&#xff0c;确保了 Java 程序能够顺利运行。今天&#xff0c;我们就深入探索 Java 虚拟机&#xff08;JVM&#xff09;是如何加载 Java 类的。 …...

Sigmoid函数导数推导详解

Sigmoid函数导数推导详解 在逻辑回归中&#xff0c;Sigmoid函数的导数推导是一个关键步骤&#xff0c;它使得梯度下降算法能够高效地计算。 1. Sigmoid函数定义 首先回顾Sigmoid函数的定义&#xff1a; g ( z ) 1 1 e − z g(z) \frac{1}{1 e^{-z}} g(z)1e−z1​ 2. 导…...

运维工作中,Ansible常用模块有哪些?

Ansible是一个强大的自动化运维工具&#xff0c;他通过模块来执行各种任务。Ansible的模块库非常丰富&#xff0c;涵盖了系统管理、文件操作、软件包管理、网络配置、云服务等多个领域。以下是Ansible中常见的模块分类及具体模块详细介绍&#xff1a; 系统管理模块 主要用于管…...

内存安全的攻防战:工具链与语言特性的协同突围

一、内存安全&#xff1a;C 开发者永恒的达摩克利斯之剑 在操作系统内核、游戏引擎、金融交易系统等对稳定性要求苛刻的领域&#xff0c;内存安全问题始终是 C 开发者的核心挑战。缓冲区溢出、悬空指针、双重释放等经典漏洞&#xff0c;每年在全球范围内造成数千亿美元的损失。…...

Linux-04-搜索查找类命令

一、find查找文件或目录: 1.基本语法: find指令将从指定目录向下递归地遍历其各个子目录1&#xff0c;将满足条件的文件显示在终端 find[搜索范围] [选项] 2.选项说明: 选项功能-name <查询方式>按照指定的文件名查找模式查找文件-user <用户名>查找属于指定用…...

移动光猫 UNG853H 获取超级管理员账号密码

注&#xff1a;电脑连接光猫&#xff0c;网线不要接2口&#xff08;2口一般是IPTV网口&#xff09; 首先浏览器打开 192.168.1.1&#xff0c;使用光猫背面的用户名密码登录。&#xff08;user用户名&#xff09; 然后在浏览器中另开一个窗口打开以下地址&#xff1a; http://…...

健康生活新主张:全方位养生指南

在追求高品质生活的今天&#xff0c;健康养生早已不是老年人的专属话题&#xff0c;而是每个人都该掌握的生活技能。科学养生不需要复杂的程序&#xff0c;而是通过日常习惯的优化&#xff0c;为身体注入源源不断的活力。 饮食管理是健康的根基。选择天然、少加工的食材&#x…...

py使用uniad原生sdk 3, 放弃Buildozer,使用BeeWare

目前&#xff0c;Buildozer 支持打包&#xff1a; Android&#xff1a;通过 Python for Android。您必须有 Linux 或 OSX computer 才能为 Android 进行编译。 iOS&#xff1a;通过 Kivy iOS。您必须拥有 OSX computer 才能为 iOS 进行编译。 支持其他平台在路线图中&#xf…...

【数据分享】2020年中国高精度森林覆盖数据集(免费获取)

森林作为全球陆地生态系统的主体&#xff0c;分布面积广、结构复杂&#xff0c;承担着调节气候、维护生态安全、改善环境等方面的重要作用。我国的森林资源丰富&#xff0c;据《中国森林资源报告&#xff1a;2014—2018》统计&#xff0c;我国森林覆盖率已经达到23.04%。森林覆…...

(007)Excel 公式的使用

文章目录 逻辑运算公式的参数常用函数引用方式引用工作表和工作簿表格的引用修改公式的计算时机区域交叉引用 逻辑运算 公式的参数 单元格引用&#xff1a;SUM(A1:A24)。字面值&#xff1a;SQRT(121)。字面文本字符串&#xff1a;PROPER(“john.f.smith”)。表达式&#xff1a…...

Vue之脚手架与组件化开发

一、基础知识 1、准备工作 node版本在12以上&#xff08;看情况而变&#xff09; 全局安装vue/cli脚手架&#xff08;不理解的可以去看一下node安装环境配置教程&#xff09; npm i vue/cli -g 2、项目初始化 在终端输入 vue create my-vue-project(这里是名字&#xff0…...

第四章 Maven

01 01. maven-课程介绍 02 02. maven-概述-maven介绍 私服&#xff1a;提高下载效率&#xff0c;让中央仓库不必被反复访问。我们一般用阿里云的私服。 03 03. maven-概述-maven安装 04 04. maven-idea集成-配置及创建maven项目 05 05. maven-idea集成-导入maven项目 06 06. …...

哈希表笔记(四)Redis对比Java总结

文章目录 一、基础结构对比数据结构定义Java HashMapRedis字典 主要区别与设计思路 二、关键操作API对比初始化Java HashMapRedis字典 添加元素Java HashMapRedis字典 查找元素Java HashMapRedis字典 删除元素Java HashMapRedis字典 扩容/重哈希操作Java HashMapRedis字典 三、…...

【精选】基于数据挖掘的广州招聘可视化分析系统(大数据组件+Spark+Hive+MySQL+AI智能云+DeepSeek人工智能+深度学习之LSTM算法)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…...

WPF使用依赖注入框架AutoMapper

WPF应用中使用AutoMapper和依赖注入框架实现对象映射与依赖管理 1. 准备工作 首先,通过NuGet安装必要的包: Install-Package AutoMapper Install-Package Autofac Install-Package Autofac.Extensions.DependencyInjection Install-Package Microsoft.Extensions.Dependen…...

WPF封装常用的TCP、串口、Modbus、MQTT、Webapi、PLC通讯工具类

WPF封装常用通讯工具类 下面我将为您封装常用的TCP、串口、Modbus、MQTT、WebAPI和PLC通讯工具类,适用于WPF应用程序开发。 一、TCP通讯工具类 using System; using System.Net.Sockets; using System.Text; using System.Threading.Tasks;public class TcpClientHelper : …...

游戏引擎学习第253天:重新启用更多调试界面

运行游戏&#xff0c;尝试调试系统&#xff0c;并为今天的工作设定方向。 今天我们将继续完成调试编辑代码的收尾工作。虽然昨天已经让它运行起来了&#xff0c;但目前还在使用旧的GUID系统&#xff0c;以及调试系统里早期用于探索阶段的一些旧式实现。因此&#xff0c;我们需…...

C# | 基于C#实现的BDS NMEA-0183数据解析上位机

以下是一个基于C#实现的BDS NMEA-0183数据解析上位机的示例代码,包含基础功能和界面: using System; using System.Collections.Generic; using System.IO.Ports; using System.Windows.Forms; using System.Drawing; using System.Globalization;namespace BDS_NMEA_Viewer…...

【AI提示词】成本效益分析师

提示说明 专注于通过数据驱动的方式提供成本效益分析&#xff0c;帮助客户优化资源投入与预期回报。 提示词 # Role: 成本效益分析师## Profile - language: 中文 - description: 专注于通过数据驱动的方式提供成本效益分析&#xff0c;帮助客户优化资源投入与预期回报 - ba…...

Kotlin革新数据分析

摘要 在数据分析领域&#xff0c;Python长期占据主导地位。然而&#xff0c;随着技术的不断发展&#xff0c;Kotlin凭借其独特优势逐渐崭露头角。本文深入探讨Kotlin在数据分析中的应用&#xff0c;详细阐述其与Python在数据分析生态系统中的差异&#xff0c;通过具体案例展示…...

今日行情明日机会——20250430

指数目前仍然在震荡区间&#xff0c;等后续的方向选择以及放量后的主线~ 2025年4月30日涨停主要行业方向分析 一、核心主线方向 机器人概念&#xff08;政策催化技术突破&#xff09; • 涨停家数&#xff1a;18家。 • 代表标的&#xff1a; ◦ 全筑股份&#xff08;工业机器…...

【Docker】Dockerfile 使用

文章目录 1. 什么是 Dockerfile?2. Dockerfile 核心指令详解2.1 基础指令2.2 构建过程指令2.3 运行时指令2.4 容器启动指令3. Dockerfile 最佳实践3.1 优化镜像构建3.2 安全性增强3.3 多阶段构建4. 完整 Dockerfile 示例5. 构建与验证6. 总结Docker 作为容器化技术的代表,已经…...

【Hive入门】Hive性能调优之资源配置:深入解析执行引擎参数调优

目录 前言 1 Hive执行引擎概述 2 MapReduce引擎调优 2.1 Map阶段资源配置 2.2 Reduce阶段资源配置 2.3 并发控制参数 3 Tez引擎调优 3.1 Tez架构概述 3.2 内存配置 3.3 并发与并行度 4 Spark引擎调优 4.1 Spark执行模型 4.2 内存管理 4.3 并行度配置 5 资源隔离…...

初学python的我开始Leetcode题8-3

提示&#xff1a;100道LeetCode热题-8-3主要是二叉树相关&#xff0c;包括三题&#xff1a;将有序数组转换为二叉搜索树、验证二叉搜索树、二叉搜索树中第K小的元素。由于初学&#xff0c;所以我的代码部分仅供参考。 目录 前言 题目1&#xff1a;将有序数组转换为二叉搜索树…...

【音频】Qt6实现MP3播放器

1、简介 解码MP3有很多种方法,比如:FFmpeg、GStreamer、Qt、libmpg123 库等,下面介绍使用,只使用Qt的接口方法解码、播放MP3。 开发配置: 1)操作系统:Windows11 2)Qt版本:Qt6.5.1 3)编译器:MinGW_64 2、获取音频输出设备 QMediaDevices 用于获取媒体设备,包括音…...

【Linux】VSCode用法

描述 部分图片和经验来源于网络&#xff0c;若有侵权麻烦联系我删除&#xff0c;主要是做笔记的时候忘记写来源了&#xff0c;做完笔记很久才写博客。 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 1 安装环境及运行C/C 1.1 安装及配置步骤 请参考这位大佬的…...

普通 html 项目也可以支持 scss_sass

项目结构示例 下载vscode的插件Live Sass Compiler 自动监听编译scss 下载插件Live Server 用于 web 服务器&#xff0c;打开 html 文件到浏览器&#xff0c;也可以不用这个&#xff0c;自己用 nginx 或者宝塔其他 web 工具 新建一个 index.scss打开&#xff0c;点击 vscode 底…...

C#实现主流PLC读写工具类封装

以下是针对三菱、欧姆龙、西门子S7系列、汇川、台达PLC的完整封装工具类实现,基于Modbus TCP/RTU、MC协议、QJ71等主流通信协议: 基础接口定义 /// <summary> /// PLC操作基础接口 /// </summary> public interface IPLC {/// <summary>/// 连接PLC/// &…...

C++之特殊类设计及类型转换

目录 一、设计一个不能被拷贝的类 二、设计一个只能在堆上创建对象的类 三、设计一个只能在栈上创建对象的类 四、设计一个不能被继承的类 五、设计一个只能创建一个对象的类(单例模式) 六、C语言中的类型转换 七、C中的三类类型转换 八、C强制类型转换 8.1、为什么C需…...

【Linux】C语言补充知识

有一些Linux常见的C语言用法需要哈好复习一下。 部分图片和经验来源于网络&#xff0c;若有侵权麻烦联系我删除&#xff0c;主要是做笔记的时候忘记写来源了&#xff0c;做完笔记很久才写博客。 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 1 结构体 1.1 结…...

怎么查看数据库容量

要查看数据库容量&#xff0c;你需要登录数据库管理系统&#xff0c;然后执行相应的 SQL 查询语句。不同的数据库管理系统有不同的语法&#xff0c;以下是一些常见的数据库管理系统中查看数据库容量的 SQL 查询语句示例&#xff1a; MySQL/MariaDB: SELECT table_schema &quo…...

深度学习中卷积的计算复杂度与内存访问复杂度

深度学习中卷积的计算复杂度与内存访问复杂度 在深度学习中&#xff0c;普通卷积&#xff08;Standard Convolution&#xff09;、深度可分离卷积&#xff08;Depthwise Separable Convolution, DWConv&#xff09;和部分卷积&#xff08;Partial Convolution, PConv&#xff…...

神经网络—损失函数

文章目录 前言一、损失函数概念二、损失函数原理1、分类问题中常见的损失函数&#xff08;1&#xff09;0-1损失函数原理优缺点 &#xff08;2&#xff09;交叉熵损失&#xff08;Cross-Entropy Loss&#xff09;原理优缺点 &#xff08;3&#xff09; 合页损失&#xff08;Hin…...

Rust中避免过度使用锁导致性能问题的策略

一、引言 在 Rust 多线程编程中&#xff0c;锁是实现线程同步的重要工具&#xff0c;它可以防止多个线程同时访问和修改共享数据&#xff0c;从而避免数据竞争和不一致的问题。然而&#xff0c;过度使用锁会带来严重的性能问题&#xff0c;如锁竞争导致的线程阻塞、上下文切换…...

Qt connect第五个参数

在 Qt 中&#xff0c;QObject::connect 函数的第五个参数用于指定 连接类型&#xff08;Qt::ConnectionType&#xff09;&#xff0c;它决定了信号与槽之间的通信方式。以下是各枚举值的详解及使用场景&#xff1a; 1. Qt::AutoConnection&#xff08;默认值&#xff09; 行为…...

QT —— 信号和槽(带参数的信号和槽函数)

QT —— 信号和槽&#xff08;带参数的信号和槽函数&#xff09; 带参的信号和槽函数信号参数个数和槽函数参数个数1. 参数匹配规则2. 实际代码示例✅ 合法连接&#xff08;槽参数 ≤ 信号参数&#xff09;❌ 非法连接&#xff08;槽参数 > 信号参数&#xff09; 3. 特殊处理…...

极简GIT使用

只为极简使用。 创建本地仓库 初始化git仓库 1.创建一个新文件夹 2.在文件夹内打开git bash 之后进入如下界面&#xff0c;输入git init&#xff0c;这样此文件就可以使用git了。 在此文件夹中&#xff0c;除了.git文件外&#xff0c;其他全部都是工作文件。 接下来将以一个…...

【嵌入式———通用定时器基本操作——实验需求2:案列:测量PWM的频率/周期】

通用定时器输入捕获 需求&#xff1a;把测到的结果通过串口发送到电脑&#xff0c;检查测试结果。 在溢出之前&#xff0c;两次上升/下降沿记录时间。 345部分 滤波器&#xff1a;用来滤掉一些毛刺信息&#xff0c;信号质量好可以不滤波 边沿检测器&#xff1a;确定要捕获的是…...

兰亭妙微:数据驱动的 B 端设计:如何用 UI 提升企业级产品体验?

​ 在数字化转型的浪潮中&#xff0c;企业级产品的用户体验成为了决定产品竞争力的关键因素。对于 B 端产品而言&#xff0c;其使用场景复杂、用户需求多元&#xff0c;如何通过 UI 设计提升产品体验&#xff0c;成为了摆在设计者面前的重要课题。而数据驱动的设计方法&#x…...

Spring AOP---面向切面编程由认识到使用

1. AOP AOP(Aspect-Oriented Programming), 是一种思想, 面向切面编程。 在前文统一异常处理&#xff0c;统一结果返回就是使用了这一思想&#xff08;都是在集中处理某一类事情, 但又不影响原有代码的正常运行&#xff09;&#xff0c;但他们不是AOP&#xff0c;只是应用了这…...

深入解析 Python 应用日志监控:ELK、Graylog 的实战指南

深入解析 Python 应用日志监控:ELK、Graylog 的实战指南 引言 在现代应用开发中,日志不仅仅是用于记录错误和调试信息,它更是系统运行状况的窗口,帮助开发者和运维人员监控、优化应用性能。Python 作为广泛应用的开发语言,其应用日志管理的重要性不言而喻。而 ELK(Elas…...

贝叶斯算法实战:从原理到鸢尾花数据集分类

贝叶斯算法实战&#xff1a;从原理到鸢尾花数据集分类 在机器学习的广阔领域中&#xff0c;贝叶斯算法以其基于概率推理的独特优势&#xff0c;成为数据分类和预测的重要工具。今天&#xff0c;我们将通过一段Python代码&#xff0c;深入探讨贝叶斯算法在鸢尾花数据集分类任务…...