概述

OSI 七层网络模型

应用层

表示层

会话层

传输层

网络层

数据链路层

可靠传输

停止等待协议

image-20231126180340362

一个一个传

回退N帧协议

image-20231126181350770

从哪里跌倒从哪里开始

累计确认

选择重传协议

不使用累计确认

物理层

TCP/IP网络模型

应用层

传输层

网络层

物理层

HTTP篇

简介

image-20231201152819271

HTTP基本概念

超文本传输协议

HTTP的名字「超⽂本协议传输」,它可以拆成三个部分:

超⽂本

传输

协议

HTTTP的状态码

image-20231201160318512

1、 HTTP Status Code 1xx 请求信息

这一组状态码表明这是一个临时性响应。此响应仅由状态行和可选的HTTP头组成,以一个空行结尾。由于HTTP/1.0未定义任何1xx状态码,所以不要向HTTP/1.0客户端发送1xx响应。

image-20231201160640034

2、 HTTP Status Code 2xx 成功状态

这一组状态码表明客户端的请求已经被服务器端成功接收并正确解析。

image-20231201160718084

3、 HTTP Status Code 3xx 重定向状态

这一组状态码表示客户端需要采取更进一步的行动来完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的Location域中指明。

image-20231201160801609

4、 HTTP Status Code 4xx 客户端错误

这一组状态码表示客户端的请求存在错误,导致服务器无法处理。除非响应的是一个HEAD请求,否则服务器就应该返回一个解释当前错误状况的实体,以及这是临时的还是永久性的状况。这些状态码适用于任何请求方法。浏览器应当向用户显示任何包含在此类错误响应中的实体内容。

Http状态码Http Status CodeHttp状态码含义中文说明
400 400 Bad Request 请求错误,通常是访问的域名未绑定引起
401 401 Unauthorized 需要身份认证验证
402 402 Payment Required -
403 403 Forbidden 禁止访问
404 404 Not Found 请求的内容未找到或已删除
405 405 Method Not Allowed 不允许的请求方法
406 406 Not Acceptable 无法响应,因资源无法满足客户端条件
407 407 Proxy Authentication Required 要求通过代理的身份认证
408 408 Request Timeout 请求超时
409 409 Conflict 存在冲突
410 410 Gone 资源已经不存在(过去存在)
411 411 Length Required 无法处理该请求
412 412 Precondition Failed 请求条件错误
413 413 Payload Too Large 请求的实体过大
414 414 Request-URI Too Long 请求的URI过长
415 415 Unsupported Media Type 无法处理的媒体格式
416 416 Range Not Satisfiable 请求的范围无效
417 417 Expectation Failed 无法满足的Expect
418 418 I'm a teapot 愚人节笑话
421 421 There are too many connections from your internet address 连接数超限
422 422 Unprocessable Entity 请求的语义错误
423 423 Locked 当前资源被锁定
424 424 Failed Dependency 当前请求失败
425 425 Unordered Collection 未知
426 426 Upgrade Required 请切换到TLS/1.0
428 428 Precondition Required 请求未带条件
429 429 Too Many Requests 并发请求过多
431 431 Request Header Fields Too Large 请求头过大
449 449 Retry With 请重试
451 451 Unavailable For Legal Reasons 访问被拒绝(法律的要求)
499 499 Client Closed Request 客户端主动关闭了连接
5、 HTTP Status Code 5xx 服务器错误状态

这一组状态码说明服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。除非这是一个HEAD请求,否则服务器应当包含一个解释当前错误状态以及这个状况是临时的还是永久的解释信息实体。浏览器应当向用户展示任何在当前响应中被包含的实体。

Http状态码Http Status CodeHttp状态码含义中文说明
500 500 Internal Server Error 服务器端程序错误
501 501 Not Implemented 服务器不支持的请求方法
502 502 Bad Gateway 网关无响应
503 503 Service Unavailable 服务器端临时错误
504 504 Gateway Timeout 网关超时
505 505 HTTP Version Not Supported 服务器不支持的HTTP版本
506 506 Variant Also Negotiates 服务器内部配置错误
507 507 Insufficient Storage 服务器无法存储请求
508 508 Loop Detected 服务器因死循环而终止操作
509 509 Bandwidth Limit Exceeded 服务器带宽限制
510 510 Not Extended 获取资源策略未被满足
511 511 Network Authentication Required 需验证以许可连接
599 599 Network Connect Timeout Error 网络连接超时

image-20231201161134206

主要字段

==主要头部字段==

首部字段名说明
Catch-Control控制缓存的行为
Connection逐条首部、连接的管理
Date创建报文的日期时间
Pragma报文指令
Trailer报文末端的首部一览
Transfer-Encoding指定报文主体的传输编码方式
Upgrade升级为其他协议
Via代理服务器的相关信息
Warning错误通知

==请求首部字段==

首部字段名说明
Accept用户代理可处理的媒体类型
Accept-Charset优先的字符集
Accept-Enconding优先的内容编码
Accept-Language优先的语言(自然语言)
AuthorizationWeb认证信息
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-AgentHTTP客户端程序的信息

==响应首部字段==

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

==实体首部字段==

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

==为Cookie服务的首部字段==

首部字段名说明首部类型
Set-Cookie开始状态管理所使用的Cookie信息响应首部字段
Cookie服务器接收到的Cookie信息请求首部字段

Get和Post的区别

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

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

而POST 方法则是相反操作,它向 URI 指定的资源提交数据,数据就放在报⽂的 body ⾥。

比如,你在我文章底部,敲入了留言后点击「提交」(暗示你们留⾔),浏览器就会执行⼀次 POST 请求,把你的留言文字放进了报文 body 里,然后拼接好 POST 请求头,通过 TCP 协议发送给服务器。

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

在 HTTP 协议里,所谓的「安全」是指请求方法不会「破坏」服务器上的资源。

所谓的「幂等」,意思是多次执行相同的操作,结果都是「相同」的。

那么很明显 GET ⽅法就是安全且幂等的,因为它是「只读」操作,无论操作多少次,服务器上的数据都是安全

的,且每次的结果都是相同的。POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的。

HTTP1.1

HTTP/1.1 的特点

  • 1.长链接 connection:keep-alive
  • 2.管道化传输,pipline
  • 3.队头阻塞。

无状态,明文传输,不安全

无状态:

无状态的好处,因为服务器不会去记忆 HTTP 的状态,所以不需要额外的资源来记录状态信息,这能减轻服务器的负担,能够把更多的 CPU 和内存⽤来对外提供服务。

无状态的坏处,既然服务器没有记忆能力,它在完成有关联性的操作时会非常麻烦。

例如登录->添加购物车->下单->结算->支付,这系列操作都要知道用户的身份才行。但服务器不知道这些请求是有关联的,每次都要问⼀遍身份信息。这样每操作⼀次,都要验证信息,这样的购物体验还能愉快吗?别问,问就是酸爽

对于无状态的问题,解法方案有很多种,其中比较简单的方式用 Cookie 技术。

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

相当于,在客户端第⼀次请求后,服务器会下发⼀个装有客户信息的「⼩贴纸」,后续客户端请求服务器的时候,

带上「⼩贴纸」,服务器就能认得了了

image-20231201163651068

明文传输

明文意味着在传输过程中的信息,是可方便阅读的,通过浏览器的 F12 控制台或 Wireshark 抓包都可以直接肉眼查看,为我们调试工作带了极大的便利性。但是这正是这样,HTTP 的所有信息都暴露在了光天化日下,相当于信息裸奔。在传输的漫长的过程中,信息的内容都毫无隐私可言,很容易就能被窃取,如果里面有你的账号密码信息,那你号没了

不安全

HTTP 比较严重的缺点就是不安全:

  • 通信使⽤明⽂(不加密),内容可能会被窃听。比如,账号信息容易泄漏,那你号没了。
  • 不验证通信⽅的身份,因此有可能遭遇伪装。比如,访问假的淘宝、拼多多,那你钱没了。
  • 无法证明报文的完整性,所以有可能已遭篡改。比如,⽹⻚上植⼊垃圾⼴告,视觉污染,眼没了。

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

  • 窃听⻛险,⽐如通信链路上可以获取通信内容,⽤户号容易没。
  • 篡改⻛险,⽐如强制植⼊垃圾⼴告,视觉污染,⽤户眼容易瞎。
  • 冒充⻛险,⽐如冒充淘宝⽹站,⽤户钱容易没。

HTTP/1.1的性能

HTTP 协议是基于 TCP/IP,并且使⽤了「请求 - 应答」的通信模式,所以性能的关键就在这两点⾥。

长连接

早期 HTTP/1.0 性能上的⼀个很大的问题,那就是每发起⼀个请求,都要新建⼀次 TCP 连接(三次握手),而且是串行请求,做了无谓的 TCP 连接建⽴和断开,增加了通信开销。

为了解决上述 TCP 连接问题,HTTP/1.1 提出了⻓连接的通信方式,也叫持久连接。这种方式的好处在于减少了

TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。

持久连接的特点是,只要任意⼀端没有明确提出断开连接,则保持 TCP 连接状态。

image-20231201164928471

管道网络传输

HTTP/1.1 采用了长连接的方式,这使得管道(pipeline)⽹络传输成为了可能。

即可在同⼀个 TCP 连接里面,客户端可以发起多个请求,只要第⼀个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。

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

但是服务器还是按照顺序,先回应 A 请求,完成后再回应 B 请求。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为「队头堵塞」。

队头阻塞

「请求 - 应答」的模式加剧了 HTTP 的性能问题。

因为当顺序发送的请求序列中的⼀个请求因为某种原因被阻塞时,在后面排队的所有请求也⼀同被阻塞了,会招致客户端⼀直请求不到数据,这也就是「队头阻塞」。好⽐上班的路上塞⻋

image-20231201165338224

HTTPS

http和https的区别

  1. HTTP 是超⽂本传输协议,信息是明⽂传输,存在安全⻛险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在

TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。

  1. HTTP 连接建⽴相对简单, TCP 三次握⼿之后便可进⾏ HTTP 的报⽂传输。⽽ HTTPS 在 TCP 三次握⼿之

后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。

  1. HTTP 的端⼝号是 80,HTTPS 的端⼝号是 443。

  2. HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。

HTTPS 解决了 HTTP 的哪些问题?

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

  • 窃听⻛险,⽐如通信链路上可以获取通信内容,⽤户号容易没。
  • 篡改⻛险,⽐如强制植⼊垃圾⼴告,视觉污染,⽤户眼容易瞎。
  • 冒充⻛险,⽐如冒充淘宝⽹站,⽤户钱容易没。

image-20231201170058911

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

信息加密:交互信息无法被窃取,但你的号会因为「自身忘记」账号而没。

校验机制:无法篡改通信内容,篡改了就不能正常显示,但百度「竞价排名」依然可以搜索垃圾广告。

身份证书:证明淘宝是真的淘宝网,但你的钱还是会因为「剁手」而没。

HTTPS是怎么解决上面三个问题的

混合加密的方式实现信息的机密性,解决了窃听的风险。

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

将服务器公钥放入到数字证书中,解决了冒充的风险。

混合加密

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

image-20231201170629230

HTTPS 采用的是对称加密⾮对称加密结合的「混合加密」方式:

在通信建立前采用非对称加密的方式交换「会话秘钥」,后续就不再使用非对称加密。

在通信过程中全部使用对称加密的「会话秘钥」的方式加密明文数据。

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

对称加密只使用⼀个密钥,运算速度快,密钥必须保密,无法做到安全的密钥交换。

⾮对称加密使用两个密钥:公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但速度慢。

摘要算法

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

image-20231201171252534

客户端在发送明文之前会通过摘要算法算出明文的「指纹」,发送的时候把「指纹 + 明文」一同加密成密文后,发送给服务器,服务器解密后,用相同的摘要算法算出发送过来的明文,通过比较客户端携带的「指纹」和当前算出的「指纹」做比较,若「指纹」相同,说明数据是完整的。

数字证书

客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。

这就存在些问题,如何保证公钥不被篡改和信任度?

所以这里就需要借助第三方权威机构 CA (数字证书认证机构),将服务器公钥放在数字证书(由数字证书认证机构颁发)中,只要证书是可信的,公钥就是可信的。

image-20231201171628966

HTTPS是如何建立连接的,期间交互了什么?

SSL/TLS 协议基本流程:

客户端向服务器索要并验证服务器的公钥。

双方协商生产「会话秘钥」。

双方采用「会话秘钥」进行加密通信。

前两步也就是 SSL/TLS 的建立过程,也就是握手阶段。

SSL/TLS 的「握手阶段」涉及四次通信,可下图:

ClientHello

首先客户端向服务端发起加密通信请求。这一步中主要包含了以下信息。

(1)客户端支持的SSL/TLS协议版本版本。

(2)客户端生产的随机数(==Client Random==),后面用于生产「会话秘钥」。

(3)客户端支持的加密算法,如RSA加密算法。

ServerHello

服务端接受到客户端发送的请求之后,返回给客户端一个回应,主要包含内容为:

(1)确认SSL/TLS版本。

(2)服务端生成的随机数,以后可以用于生成会话密钥。

(3)客户端支持的加密算法,比如说RSA算法。

(4)服务器的数字证书。

客户端响应

客户端收到服务器的相应之后,首先通过浏览器或者操作系统中的CA公钥,确认服务器的数字公钥的正确性。如果服务器的公钥没有问题,那么我们就会利用该公钥,对发送的内容进行加密。加密的内容主要包含了一下三个方面:

(1)客户端随机数,用于会话密钥的生成。

(2)服务器握手结束通知,表示服务器的握手阶段已经结束,之后的通信都用会话密钥进行通信。

(3)这一项将之前所有的通信内容做一个摘要供服务端校验。

上面第⼀项的随机数是整个握手阶段的第三个随机数,这样服务器和客户端就同时有三个随机数,接着就用双方协商的加密算法,各⾃⽣成本次通信的「会话秘钥」。

服务端响应

服务器收到客户端的第三个随机数( pre-master key)之后,通过协商的加密算法,计算出本次通信的「会话秘钥」。然后,向客户端发出最后的信息:

(1)加密方式改变通知。

(2)服务端握手结束通知,并将之前的通信做一次摘要。

至此,整个 SSL/TLS 的握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用「会话秘钥」加密内容。

HTTP/1.1、HTTP/2、HTTP/3 演变

首先谈及的是HTTP1.1相对于HTTP1.0提升了什么:

(1)HTTP1.1引入了长链接,这样的发送多个HTTP请求就不需要进行多次建立连接了,使用connection:keep-alive来进行控制。

(2)就是管道化网络传输(pipline),在没有接受到客户端第一个请求回应的时候,就可以发送第二个网络请求。

HTTP1.1的问题:

(1)头部阻塞:在http1.1的管道化传输中,虽然可以同时发送多个请求,但是只有收到第一个请求之后才能接受之后的请求,所以说如果第一个(对头)发生了阻塞,那么我们之后所有的请求都会被阻塞。

(2)头部冗长重复:每次发送http都要发送一个冗长的请求,但是绝大部分重复的部分居多。

(3)在该过程中,客户端永远都是发起方,服务端永远都是被动方。

HTTP2.0相对于HTTP1.1的性能提升之处:

  1. 头部压缩,HTTP/2会压缩头部,对于HTTP1.1中的大量重复冗余的头部而言,可以消除重复的部分。

    HTTP/2 会压缩头(Header)如果你同时发出多个请求,他们的头是⼀样的或是相似的,那么,协议会帮你消除重复的部分。这就是所谓的 HPACK 算法:在客户端和服务器同时维护⼀张头信息表,所有字段都会存⼊这个表,⽣成⼀个索引号,以后就不发送同样字段了,只发送索引号,这样就提⾼速度了。

  2. 二进制格式,不再像HTTP1.1中那种纯文本格式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,紧切统称为帧:头信息帧和数据帧。二进制帧的形式,计算机在收到报文之后,不需要转化为二进制,而是直接将该报文解析,这增加了数据传输的效率。

    image-20231201173940335

  3. 数据流(多路复用):

HTTP/2 的数据包不是按顺序发送的,同⼀个连接⾥⾯连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。每个请求或回应的所有数据包,称为⼀个数据流( Stream )。每个数据流都标记着⼀个独⼀⽆⼆的编号,其中规定客户端发出的数据流编号为奇数, 服务器发出的数据流编号为偶数客户端还可以指定数据流的优先级。优先级⾼的请求,服务器就先响应该请求。

image-20231201174304174

  1. 多路复用:

    HTTP/2 是可以在⼀个连接中并发多个请求或回应,⽽不⽤按照顺序⼀⼀对应

    移除了 HTTP/1.1 中的串⾏请求,不需要排队等待,也就不会再出现「队头阻塞」问题,降低了延迟,⼤幅度提⾼了连接的利⽤率。举例来说,在⼀个 TCP 连接⾥,服务器收到了客户端 A 和 B 的两个请求,如果发现 A 处理过程⾮常耗时,于是就回应 A 请求已经处理好的部分,接着回应 B 请求,完成后,再回应 A 请求剩下的部分。

    image-20231201174715702

  1. 服务器推送

    HTTP/2 还在⼀定程度上改善了传统的「请求 - 应答」⼯作模式,服务不再是被动地响应,也可以主动向客户端发送消息。举例来说,在浏览器刚请求 HTML 的时候,就提前把可能会⽤到的 JS、CSS ⽂件等静态资源主动发给客户端,减少延时的等待,也就是服务器推送(Server Push,也叫 Cache Push)。

HTTP3相对于HTTP2的提升?

HTTP/2 主要的问题在于,多个HTTP请求在复用一个TCP连接,下层的TCP协议是不知道有多少个HTTP请求的。所以一旦发送丢包的情况,就会触发TCP的重传机制,这样在一个TCP连接中的所有的HTTP请求都必须要去等待这个丢了的包被重传回来。

image-20231201175003850

  1. HTTP/1.1中的管道(pipline)传输中如果有一个请求阻塞了,那么队列后请求也统统会被阻塞住。
  2. HTTP/2多个请求服用一个TCP链接,一旦发生了丢包,就会阻塞住所有的HTTP请求。

这些其实都是在TCP传输层出了问题,所以HTTP3的时候就把HTTP下层的TCP更换为了UDP!UDP实现了一个不可靠传输,但是基于 UDP 的 QUIC 协议可以实现类似于 TCP 的可靠传输。

  1. QUIC 有自己的一套机制可以保证传输的可靠性。当某一个流发生丢包的时候,只会阻塞这个流,不会影响到其他的流。
  2. TLS3 升级到最新的1.3版本,头部压缩变为QPack。
  3. HTTPS要建立连接的话,要花费6次交互,先是要建立三次握手,然后是TLS的三次握手。QUIC直接把之前的TCP和TLS/1.3的三次握手合并为了3次,减少了交互的次数。所以说QUIC是一个新的协议,它是一个伪TCP+TLS+HTTP/2的多路复用的协议。

HTTPS RSA握手解析

RSA加密算法

image-20230902135332890

TLS握手解析

RSA握手过程

总述
TLS第一次握手
TLS第二次握手
TLS第三次握手
TLS第四次握手

RSA算法缺陷

HTTPS ECDHE

总述

离散对数

DH算法

DHE算法

ECDHE算法

ECDHE算法过程

TLS第一次握手
TLS第二次握手
TLS第三次握手
TLS第四次握手

HTTPS如何优化

分析性能损耗

硬件优化

软件优化

协议优化

证书优化

会话复用

总结

HTTP/2

HTTP/1.1协议的性能问题

兼容HTTP/1.1

头部压缩

二进制帧

并发传输

服务器主动推送资源

HTTP/3

HTTP/2中存在问题

QUIC协议特点

HTTP/3协议

HTTP/1.1优化

问你⼀句:「你知道 HTTP/1.1 该如何优化吗?

我想你第⼀时间想到的是,使用 KeepAlive 将 HTTP/1.1 从短连接改成长链接。这个确实是⼀个优化的手段,它是从底层的传输层这⼀方向入手的,通过减少 TCP 连接建立和断开的次数,来减少了网络传输的延迟,从而提高 HTTP/1.1 协议的传输效率。

但其实还可以从其他方向来优化 HTTP/1.1 协议,比如有如下 3 种优化思路:

  • 尽量避免发送 HTTP 请求;

  • 在需要发送 HTTP 请求时,考虑如何减少请求次数;

  • 减少服务器的 HTTP 响应的数据大小;

image-20231201175727120

如何避免发送 HTTP 请求?

对于⼀些具有重复性的 HTTP 请求,⽐如每次请求得到的数据都⼀样的,我们可以把这对「请求-响应」的数据都缓存在本地,那么下次就直接读取本地的数据,不必在通过⽹络获取服务器的响应了,这样的话 HTTP/1.1的性能肯定⾁眼可⻅的提升。所以,避免发送 HTTP 请求的⽅法就是通过缓存技术,HTTP 设计者早在之前就考虑到了这点,因此 HTTP 协议的头部有不少是针对缓存的字段。

那缓存是如何做到的呢?

客户端会把第⼀次请求以及响应的数据保存在本地磁盘上,其中将请求的 URL 作为 key,⽽响应作为 value,两者形成映射关系。这样当后续发起相同的请求时,就可以先在本地磁盘上通过 key 查到对应的 value,也就是响应,如果找到了,就直接从本地读取该响应。毋庸置疑,读取本次磁盘的速度肯定⽐⽹络请求快得多,如下图:

image-20231201180103821

聪明的你可能想到了,万⼀缓存的响应不是最新的,⽽客户端并不知情,那么该怎么办呢?

放⼼,这个问题 HTTP 设计者早已考虑到。

所以,服务器在发送 HTTP 响应时,会估算⼀个过期的时间,并把这个信息放到响应头部中,这样客户端在查看响

应头部的信息时,⼀旦发现缓存的响应是过期的,则就会᯿新发送⽹络请求。HTTP 关于缓说明会的头部字段很

多,这部分内容留在下次⽂章,这次暂时不具体说明。如果客户端从第⼀次请求得到的响应头部中发现该响应过期了,客户端᯿新发送请求,假设服务器上的资源并没有

变更,还是⽼样⼦,那么你觉得还要在服务器的响应带上这个资源吗?

很显然不带的话,可以提⾼ HTTP 协议的性能,那具体如何做到呢?

只需要客户端在᯿新发送请求时,在请求的 Etag 头部带上第⼀次请求的响应头部中的摘要,这个摘要是唯⼀标

识响应的资源,当服务器收到请求后,会将本地资源的摘要与请求中的摘要做个⽐较。

如果不同,那么说明客户端的缓存已经没有价值,服务器在响应中带上最新的资源。

如果相同,说明客户端的缓存还是可以继续使⽤的,那么服务器仅返回不含有包体的 304 Not Modified 响应

告诉客户端仍然有效,这样就可以减少响应资源在⽹络中传输的延时,如下图:

image-20231201221600858

如何减少 HTTP 请求次数?

减少重定向请求次数;

合并请求;

延迟发送请求;

TCP篇

TCP三次握手四次挥手

TCP重传,滑动窗口,流量控制,拥塞控制

image-20230909190436664

重传机制

TCP实现可靠传输的方式之一,是通过序列号与确定应答

在TCP中,当发送端的数据到达主机时,接收端主机会返回一个确认消息,表示已经收到消息。

image-20230909191008768

超时重传

在数据发送过程中有两种情况会导致超时重传。

在发送端数据到接收端时,接收端没有接收到数据。

接收端接收到了数据,但是发给发送端的确认消息丢失了。

image-20230909191402422

超时重传是根据超时时间(Retransmission Timeout)来确定的

超时时间设置是根据RTT来设置的

RTT(Round-Trip Time)是指数据从网络一端传送到另一端所需要的时间,通俗的讲应该是一来一回的时间。

image-20230909191707500

超时时间(RTO)的设置不能太长和太短。

设置太长:重发太慢,丢了之后可能一直都不发送,隔了好长时间都不发送。

设置太短:可能包还没有丢失就重新发送了,导致重复发送。此时更多的重发包可能会导致网络堵塞,网络堵塞再导致更多的重发,会陷入恶性循环。

image-20230909192522336

所以最后的结论应该是RTO的值应该略大于RTT的值。

image-20230909192652781

此时可以想一想:RTT得值会随着网络波动的变化和变化,而RTO的值应该略大于RTT的值,所以RTT的值应该也是动态变化的。

那么RTO的值应该怎么确定呢?

Linux计算RTO的方式:

需要 TCP 通过采样 RTT 的时间,然后进⾏加权平均,算出⼀个平滑 RTT 的值,⽽且这个值还是要不断变化的,因为⽹络状况不断地变化。

除了采样 RTT,还要采样 RTT 的波动范围,这样就避免如果 RTT 有⼀个⼤的波动的话,很难被发现的情况。

大概计算的方式应该就是这样,当然这里用到一些计算算法。感兴趣可以去了解一下。

最后通过RTT计算出RTO的一个略大于RTT的值。

快速重传

另一种重传机制为快速重传,它不像超时重传一样以时间为基准,而是以数据驱动重传。

image-20230909194051373

发送了上图所示的5份数据:

  • 第⼀份 Seq1 先送到了,于是就 Ack 回 2;

  • 结果 Seq2 因为某些原因没收到,Seq3 到达了,于是还是 Ack 回 2;

  • 后⾯的 Seq4 和 Seq5 都到了,但还是 Ack 回 2,因为 Seq2 还是没有收到;

  • 发送端收到了三个 Ack = 2 的确认,知道了 Seq2 还没有收到,就会在定时器过期之前,重传丢失的 Seq2

  • 最后,收到了 Seq2,此时因为 Seq3,Seq4,Seq5 都收到了,于是 Ack 回 6 。

所以,快速重传的工作方式是当收到三个相同的 ACK 报⽂时,会在定时器过期之前,᯿传丢失的报⽂段。

快速重传传机制只解决了⼀个问题,就是超时时间的问题,但是它依然⾯临着另外⼀个问题。就是**重传的时候,是重传之前的⼀个,还是重传所有的问题。

比如对于上面的这些例子,是重传 Seq2 呢?还是重传 Seq2、Seq3、Seq4、Seq5 呢?因为发送端并不清楚这连续的

三个 Ack 2 是谁传回来的。

根据 TCP 不同的实现,以上两种情况都是有可能的。可⻅,这是⼀把双刃剑。

为了解决不知道该᯿传哪些 TCP 报⽂,于是就有 SACK ⽅法。

SACK

还有⼀种实现重传机制的⽅式叫: SACK ( Selective Acknowledgment 选择性确认)。

这种方式需要在 TCP 头部「选项」字段⾥加⼀个 SACK 的东⻄,它可以将缓存的地图发送给发送⽅,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据

如下图,发送⽅收到了三次同样的 ACK 确认报⽂,于是就会触发快速重发机制,通过 SACK 信息发现只有

200~299 这段数据丢失,则重发时,就只选择了这个 TCP 段进行重复。

image-20231123201039436

如果要支持 SACK ,必须双方都要支持。在 Linux 下,可以通过net.ipv4.tcp_sack参数打开这个功能(Linux

2.4 后默认打开)

D-SACK

Duplicate SACK 又称 D-SACK ,其主要使⽤了 SACK 来告诉「发送⽅」有哪些数据被重复接收了。

滑动窗口

我们都知道 TCP 是每发送⼀个数据,都要进⾏⼀次确认应答。当上⼀个数据包收到了应答了, 再发送下⼀个。这个模式就有点像我和你⾯对⾯聊天,你⼀句我⼀句。但这种⽅式的缺点是效率⽐较低的。如果你说完⼀句话,我在处理其他事情,没有及时回复你,那你不是要⼲等着我做完其他事情后,我回复你,你才能说下⼀句话,很显然这不现实。

image-20231123201443520

所以,这样的传输⽅式有⼀个缺点:数据包的往返时间越⻓,通信的效率就越低

为解决这个问题,TCP 引入了窗⼝这个概念。即使在往返时间较长的情况下,它也不会降低网络络通信的效率。

那么有了窗⼝,就可以指定窗⼝⼤⼩,窗⼝⼤⼩就是指⽆需等待确认应答,⽽可以继续发送数据的最⼤值

窗⼝的实现实际上是操作系统开辟的⼀个缓存空间,发送⽅主机在等到确认应答返回之前,必须在缓冲区中保留已

发送的数据。如果按期收到确认应答,此时数据就可以从缓存区清除。

假设窗口大小为 3 个 TCP 段,那么发送⽅就可以「连续发送」 3 个 TCP 段,并且中途若有 ACK 丢失,可以

通过「下⼀个确认应答进⾏确认」。如下图

image-20231123201554056

图中的 ACK 600 确认应答报⽂丢失,也没关系,因为可以通过下⼀个确认应答进⾏确认,只要发送⽅收到了 ACK

700 确认应答,就意味着 700 之前的所有数据「接收⽅」都收到了。这个模式就叫累计确认或者累计应答

滑动窗口由哪一方决定?

TCP 头⾥有⼀个字段叫 Window ,也就是窗⼝⼤⼩。

这个字段是接收端告诉发送端⾃⼰还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能⼒来

发送数据,⽽不会导致接收端处理不过来。

所以,通常窗⼝的⼤⼩是由接收⽅的窗⼝⼤⼩来决定的。

发送⽅发送的数据⼤⼩不能超过接收⽅的窗⼝⼤⼩,否则接收⽅就⽆法正常接收到数据。

发送方的滑动窗口

我们先来看看发送⽅的窗⼝,下图就是发送⽅缓存的数据,根据处理的情况分成四个部分,其中深蓝⾊⽅框是发送窗⼝,紫⾊⽅框是可⽤窗⼝:

image-20231123201826213

  • #1 是已发送并收到 ACK确认的数据:1~31 字节
  • #2 是已发送但未收到 ACK确认的数据:32~45 字节
  • #3 是未发送但总⼤⼩在接收⽅处理范围内(接收⽅还有空间):46~51字节
  • #4 是未发送但总⼤⼩超过接收⽅处理范围(接收⽅没有空间):52字节以后

在下图,当发送⽅把数据「全部」都⼀下发送出去后,可⽤窗⼝的⼤⼩就为 0 了,表明可⽤窗⼝耗尽,在没收到

ACK 确认之前是⽆法继续发送数据了。

image-20231123201942045

在下图,当收到之前发送的数据 32~36 字节的 ACK 确认应答后,如果发送窗⼝的⼤⼩没有变化,则滑动窗⼝往

右边移动 5 个字节,因为有 5 个字节的数据被应答确认,接下来 52~56 字节⼜变成了可⽤窗⼝,那么后续也就

可以发送 52~56 这 5 个字节的数据了。

image-20231123202017368

程序是如何表示发送方的这4个部分?

TCP 滑动窗⼝⽅案使⽤三个指针来跟踪在四个传输类别中的每⼀个类别中的字节。其中两个指针是绝对指针(指特定的序列号),⼀个是相对指针(需要做偏移)。

image-20231123202155764

  • SND.WND :表示发送窗⼝的⼤⼩(⼤⼩是由接收⽅指定的);
  • SND.UNA :是⼀个绝对指针,它指向的是已发送但未收到确认的第⼀个字节的序列号,也就是 #2 的第⼀个字节。
  • SND.NXT :也是⼀个绝对指针,它指向未发送但可发送范围的第⼀个字节的序列号,也就是 #3 的第⼀个字节。
  • 指向 #4 的第⼀个字节是个相对指针,它需要 SND.UNA 指针加上 SND.WND ⼤⼩的偏移量,就可以指向#4 的第⼀个字节了。

那么可⽤窗⼝⼤⼩的计算就可以是:

==可⽤窗⼝⼤小 = SND.WND -(SND.NXT - SND.UNA)==

接收方的滑动窗口

接下来我们看看接收⽅的窗⼝,接收窗⼝相对简单⼀些,根据处理的情况划分成三个部分:

  • #1 + #2 是已成功接收并确认的数据(等待应⽤进程读取);
  • #3 是未收到数据但可以接收的数据;
  • #4 未收到数据并不可以接收的数据

image-20231123202526928

其中三个接收部分,使⽤两个指针进⾏划分:

  • RCV.WND :表示接收窗⼝的⼤⼩,它会通告给发送⽅。
  • RCV.NXT :是⼀个指针,它指向期望从发送⽅发送来的下⼀个数据字节的序列号,也就是 #3 的第⼀个字节。
  • 指向 #4 的第⼀个字节是个相对指针,它需要 RCV.NXT 指针加上 RCV.WND ⼤⼩的偏移量,就可以指向#4 的第⼀个字节了。

发送方和接受方的滑动窗口是相等的吗

并不是完全相等,接收窗⼝的⼤⼩是约等于发送窗⼝的⼤⼩的。

因为滑动窗⼝并不是⼀成不变的。⽐如,当接收⽅的应⽤进程读取数据的速度⾮常快的话,这样的话接收窗⼝可以很快的就空缺出来。那么新的接收窗⼝⼤⼩,是通过 TCP 报⽂中的 Windows 字段来告诉发送⽅。那么这个传输过程是存在时延的,所以接收窗⼝和发送窗⼝是约等于的关系。

流量控制

发送方不能无脑的给接收方发送,必须考虑接收方的接受能力

为了解决这种现象发⽣,TCP 提供⼀种机制可以让「发送⽅」根据「接收⽅」的实际接收能⼒控制发送的数据量,

这就是所谓的流量控制。

下⾯举个栗⼦,为了简单起⻅,假设以下场景:

  • 客户端是接收⽅,服务端是发送⽅
  • 假设接收窗⼝和发送窗⼝相同,都为 200
  • 假设两个设备在整个传输过程中都保持相同的窗⼝⼤⼩,不受外界影响

image-20231123203010366

拥塞控制

TCP实战抓包分析

TCP半连接参数和全连接参数

TCP内核参数

IP篇

IP基础知识

IP基本认识

IP地址基础知识

IP协议相关技术

DNS协议
ARP协议
DHCP协议
NAT
ICMP
IGMP

路由选择协议

RIP
OSPF

链路状态通告LSA

链路状态更新分组LSU,洪泛法

死亡倒计时

LSDB

有向图,图的最短路径优先算法计算

问候分组

数据库描述分组

链路状态请求分组

链路状态更新分组

链路状态确认分组

多播问题解决

指定路由器DR和备用指定路由器BDR

选举的一些问题

划分区域解决洪泛法的问题

区域边界路由器,均与主干区域相连接

自治系统边界路由器,与其他自治系统进行交换

BGP(外界网关协议)

能到达目的地的较好的路由(需要考虑政治,经济,安全等因素)

BGP边界路由器

BGP4的四种报文

OPEN报文

UPDATE报文

KEEPALIVE报文

NOTIFICATION报文

封装RIP,OSPF,BGP的报文分别是UDP,IP,TCP

ping的实战原理

网络综合篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值