第2期 - 豫园闲逛

封面图来源于豫园街边集市小摊,上海少有的存在烟火气的地方,元宵或中秋去应该会更有氛围。

杏花楼

技术分享-网络相关

TCP

TCP 的全称叫传输控制协议(Transmission Control Protocol),大部分应用使用的正是 TCP 传输层协议,比如 HTTP 应用层协议。TCP 相比 UDP 多了很多特性,比如流量控制、超时重传、拥塞控制等,这些都是为了保证数据包能可靠地传输给对方。

UDP

UDP 相对来说就很简单,简单到只负责发送数据包,不保证数据包是否能抵达对方,但它实时性相对更好,传输效率也高。当然,UDP 也可以实现可靠传输,把 TCP 的特性在应用层上实现就可以,不过要实现一个商用的可靠 UDP 传输协议,也不是一件简单的事情。

DNS

通过浏览器解析 URL 并生成 HTTP 消息后,需要委托操作系统将消息发送给 Web 服务器。但在发送之前,还有一项工作需要完成,那就是查询服务器域名对应的 IP 地址,因为委托操作系统发送消息时,必须提供通信对象的 IP 地址。 所以,有一种服务器就专门保存了 Web 服务器域名与 IP 的对应关系,它就是 DNS 服务器。

DNS解析过程

客户端首先会发出一个 DNS 请求,问 www.server.com 的 IP 是啥,并发给本地 DNS 服务器(域名中,越靠右的位置表示其层级越高) 本地域名服务器收到客户端的请求后,如果缓存里的表格能找到 www.server.com 则它直接返回 IP 地址。如果没有,本地 DNS 会去问它的根域名服务器,直至找到完整的IP地址,DNS 服务器查询后将对应的 IP 地址 X.X.X.X 告诉本地 DNS,本地 DNS 再将 IP 地址返回客户端,客户端和目标建立连接。

CDN

DNS 全称 Domain Name System,CDN 全称 Content Delivery Network CDN 加速内容传输和提供更好的用户体验,包括一系列分布在全球各地的服务器节点,这些节点存储网站的静态和动态内容(如图像、视频、CSS、JavaScript等)的副本。当用户请求访问一个网站时,CDN会自动选择最接近用户地理位置的服务器节点来提供内容,从而减少加载时间和延迟。通过减少数据传输的距离,提高网站的加载速度,减轻源服务器的负担。

MAC (网络接口层)

用来在局域网中识别自己 MAC 头部是以太网使用的头部,它包含了接收方和发送方的 MAC 地址等信息。 负责在物理介质上传输数据帧。它包含了源 MAC 地址和目标 MAC 地址,用于确定数据帧的发送和接收方。在以太网中,MAC 地址是设备的物理地址,用于在局域网中唯一标识每个网络设备。MAC 头部还包括一些其他信息,如帧类型和长度等,以帮助网络设备正确地处理数据帧。

MAC 包头的协议类型使用 IP 协议,表示数据帧中的有效数据是IP数据,接收方会将数据交给IP协议栈进行处理 ARP 协议,用于在局域网内进行IP地址到MAC地址的映射和解析的协议

IP 协议(网络层)

唯一标识设备或主机的地址,在网络层实现路由和寻址 网络层最常使用的是 IP 协议(Internet Protocol),IP 协议会将传输层的报文作为数据部分,再加上 IP 包头组装成 IP 报文,如果 IP 报文大小超过 MTU(以太网中一般为 1500 字节)就会再次进行分片,得到一个即将发送到网络的 IP 报文。

在 IP 协议里面需要有源地址 IP 和 目标地址 IP: 源地址IP,即是客户端输出的 IP 地址; 目标地址,即通过 DNS 域名解析得到的 Web 服务器 IP。

IP协议和ARP协议 协同过程

MAC地址主要用于局域网内的设备寻址,而IP地址用于在不同网络之间进行设备寻址和路由 IP协议和ARP协议在局域网通信中互相协同工作,共同完成IP地址和物理MAC地址之间的转换和映射过程

IP协议的角色: IP协议负责在不同网络之间进行寻址、路由和数据包传递。它使用IP地址来标识不同主机和网络,确保数据可以从源主机正确地传递到目标主机。然而,在局域网内,直接使用IP地址进行通信可能并不高效,因为局域网通常是基于MAC地址的。

ARP协议的角色: ARP协议负责在局域网内解析IP地址和MAC地址之间的映射关系。当设备需要通过IP地址与其他设备通信时,它会使用ARP协议向网络广播一个ARP请求,询问某个IP地址对应的MAC地址。其他设备检查自己的IP地址,如果与请求匹配,就会回复包含自己的MAC地址的ARP响应。

协同工作过程: 当一台设备(计算机A)想要与另一台设备(计算机B)通信时,计算机A可能只知道计算机B的IP地址。在这种情况下,协同工作如下:

计算机A使用IP协议构建一个IP数据包,目标IP地址是计算机B的IP地址。 计算机A发送一个ARP请求,询问网络中是否有计算机B的MAC地址。 如果计算机B在同一局域网内,它会回复一个ARP响应,包含自己的MAC地址。 计算机A收到ARP响应后,获得了计算机B的MAC地址。 计算机A可以将IP数据包封装在以太网数据帧中,设置目标MAC地址为计算机B的MAC地址,然后通过局域网发送数据。

协同工作使得设备能够通过IP地址进行通信,同时能够在局域网中查找和获得目标设备的MAC地址。IP协议处理跨网络通信,而ARP协议则处理局域网内的IP到MAC地址映射。

TCP 连接

三次握手

TCP 是面向连接的协议,所以使用 TCP 前必须先建立连接,而建立连接是通过三次握手来进行的

  • 第一步:客户端发送 SYN: 客户端向服务器发送一个 SYN(同步序列编号)包,表明客户端准备建立连接。客户端选择一个随机初始序列号(ISN)。
  • 第二步:服务器回应 SYN+ACK: 服务器接收到客户端的 SYN 包后,会发送一个 SYN+ACK 包作为响应。服务器确认了客户端的 SYN 包,并选择一个随机初始序列号作为服务器的 ISN。
  • 第三步:客户端确认 ACK: 客户端接收到服务器的 SYN+ACK 包后,发送一个确认(ACK)包,确认了服务器的 SYN+ACK 包。同时,客户端也确认了自己之前发送的 SYN 包。此时,连接已建立,双方可以开始传输数据。

四次挥手

TCP 断开连接是通过四次挥手方式

  • 第一步:客户端发送 FIN: 当客户端完成数据传输后,它发送一个 FIN 包,表示已经没有更多的数据要发送了,但仍然可以接收数据。
  • 第二步:服务器回应 ACK: 服务器接收到客户端的 FIN 包后,发送一个确认(ACK)包,确认客户端的 FIN 包。服务器此时进入关闭等待状态。
  • 第三步:服务器发送 FIN: 当服务器也完成数据传输后,它发送一个 FIN 包,表示服务器没有更多数据要发送了。同时,服务器也可以接收数据。
  • 第四步:客户端回应 ACK: 客户端接收到服务器的 FIN 包后,发送一个确认(ACK)包,确认服务器的 FIN 包。此时,连接完全关闭,双方都无法再发送数据。

在一些情况下, TCP 四次挥手是可以变成 TCP 三次挥手的。 通常情况,服务器收到客户端的 FIN 报文时,内核会马上回一个 ACK 应答报文,但是服务端应用程序可能还有数据要发送,所以并不能马上发送 FIN 报文,而是将发送 FIN 报文的控制权交给服务端应用程序 而当被动关闭方(上图的服务端)在 TCP 挥手过程中,「没有数据要发送」并且「开启了 TCP 延迟确认机制」,那么第二和第三次挥手就会合并传输,这样就出现了三次挥手。

网络模型

TCP/IP 四层模型

TCP/IP 网络通常是由上到下分成 4 层,分别是应用层,传输层,网络层和网络接口层。

应用层:我们能直接接触到的就是应用层 应用层是最高层,负责提供用户与网络之间的接口。它支持不同类型的应用程序,如Web浏览器、电子邮件客户端等。在这个层次,数据被格式化并传递给应用程序,应用层协议(如HTTP、SMTP、FTP)定义了数据交换的规则

传输层:传输层会有两个传输协议,分别是 TCP 和 UDP 传输层负责端到端通信和数据传输的可靠性。它使用端口号来标识不同的应用程序,提供了流量控制、错误检测和恢复机制。最常见的传输层协议是TCP(传输控制协议)和UDP(用户数据报协议)。

网络层:网络层负责将数据从一个设备传输到另一个设备(通过IP协议指定) 我们不希望传输层协议处理太多的事情,只需要服务好应用即可,让其作为应用间数据传输的媒介,帮助实现应用到应用的通信,而实际的传输功能就交给下一层,也就是网络层

网络接口层:生成了 IP 头部之后,接下来要交给网络接口层(Link Layer)在 IP 头部的前面加上 MAC 头部,并封装成数据帧(Data frame)发送到网络上。 链路层处理数据在物理网络中的传输和帧同步。它负责将原始数据分成帧,添加物理地址(MAC地址)和错误检测等。以太网是链路层的常见协议

OSI七层模型

应用层:负责应用程序和用户之间的通信

表示层:负责数据的格式转换、数据加密和解密、数据压缩和字符编码

会话层:由操作系统提供支持,负责建立、管理和终止通信会话

传输层:提供端到端的数据传输服务,负责数据的可靠传输、错误检测和纠正,以及数据的分段和重组。最常见的传输层协议是 TCP 和 UDP

网络层:定义了IP地址、路由表和路由算法,负责数据包的路由、寻址和跨不同网络的传输

数据链路层:负责数据的分帧、物理地址分配(如MAC地址)和数据的流控制。

物理层:负责定义传输媒体、数据的编码方式和物理连接标准。

HTTP

基于 TCP 传输协议进行通信 超文本传输协议(HyperText Transfer Protocol) 超文本:是文字、图片、视频等的混合体。HTML 就是最常见的超文本

常见字段

Host 字段: 可以将请求发往「同一台」服务器上的不同网站。客户端发送请求时,用来指定服务器的域名。

Host: www.A.com

Content-Length 字段: 本次回应的数据长度

Content-Length: 1000

Connection 字段:最常用于客户端要求服务器使用「HTTP 长连接」机制,以便其他请求复用

Connection: Keep-Alive

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

 text/html; application/json; charset=UTF-8

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

Content-Encoding: gzip

客户端在请求时,用 Accept-Encoding 字段说明自己可以接受哪些压缩方法

Accept-Encoding: gzip, deflate

HTTP 长连接

只要任意一端没有明确提出断开连接,则保持 TCP 连接状态

GET 与 POST

GET

GET 的语义是从服务器获取指定的资源, 静态的文本、页面、图片视频等 如 打开一个url,浏览器就会发送 GET 请求给服务器,服务器就会返回该网页下的所有文字及资源

安全、幂等、可被缓存的。 是「只读」操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。所以可以对 GET 请求的数据进行缓存

例外情况(非RFC规范): 可以用 GET 方法实现新增或删除数据的请求,这样实现的 GET 方法自然就不是安全和幂等 GET 请求也可以带 body

POST

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

POST 请求携带数据的位置一般是写在报文 body 中,body 中的数据可以是任意格式的数据,只要客户端与服务端协商好即可,而且浏览器不会对 body 大小做限制。

不安全,不幂等,(大部分实现)不可缓存。 会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的。所以浏览器一般不会缓存 POST 请求,也不能把 POST 请求保存为书签。

例外情况(非RFC规范): 可以用 POST 方法实现查询数据的请求,这样实现的 POST 方法自然就是安全和幂等 URL 中的查询参数也不是 GET 所独有的,POST 请求的 URL 中也可以有参数的

http 与 https

GET 不如 POST 安全?实际上, HTTP 传输的内容都是明文的。要避免传输过程中数据被窃取,就要使用 HTTPS 协议。所有 HTTP 的数据都会被加密传输

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

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

http: 窃听风险、篡改风险、冒充风险 https: 信息加密、校验机制、身份证书

https

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

SSL/TLS 协议基本流程(TLS 握手阶段): 客户端向服务器索要并验证服务器的公钥。 双方协商生产「会话秘钥」。 双方采用「会话秘钥」进行加密通信。

https中间人攻击

通过伪造HTTPS证书来实现,伪装服务器建立加密连接,而不是与真正的目标服务器建立连接。 在经过攻击者的服务器之前进行了解密和再加密。 攻击者查看、篡改或窃取双方之间的通信数据 窃取敏感信息,如用户名、密码、信用卡信息等,或者在不被察觉的情况下监控通信内容

加密方式

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

https 中间人攻击过程

HTTPS的整体过程分为证书验证和数据传输阶段。内容传输使用对称加密,非对称加密只作用在证书验证阶段。

证书验证-> 数据传输 浏览器发起 HTTPS 请求, 服务端返回 HTTPS 证书, 客户端验证证书是否合法,如果不合法则提示告警 当证书验证合法后,在本地生成随机数,通过公钥加密随机数,并把加密后的随机数传输到服务端,服务端通过私钥对随机数进行解密,再通过随机数构造对称加密算法,对返回结果内容进行加密后传输

非对称加密

  • 非对称加密的加解密效率较低
  • 使用一对密钥,公钥和私钥。公钥用于加密数据,而私钥用于解密数据,公钥可自由共享,而私钥必须保密
  • 非对称加密用于数据的安全传输,数字签名验证和身份验证等场景

对称加密

  • 对称加密使用相同的密钥(称为加密密钥)来加密和解密数据
  • 由于使用相同的密钥进行加密和解密,对称加密速度快,但需确保密钥的安全传输和存储,因为一旦密钥泄露,所有数据都可能受到威胁
  • 对称加密通常用于保护大量数据的机密性,例如文件传输或大规模数据存储

中间人攻击过程 本地请求被劫持(如DNS劫持等),所有请求均发送到中间人的服务器,中间人服务器返回中间人自己的证书 客户端创建随机数,通过中间人证书的公钥对随机数加密后传送给中间人,然后凭随机数构造对称加密对传输内容进行加密传输。因为拥有客户端的随机数,可以通过对称加密算法进行内容解密,以客户端的请求内容再向正规网站发起请求,因为中间人与服务器的通信过程是合法的,正规网站通过建立的安全通道返回加密后的数据,中间人凭借与正规网站建立的对称加密算法对内容进行解密,和返回的数据进行加密传输,客户端进行数据解密。中间人悄无声息模拟了正规网站的整个过程

浏览器发起 HTTPS 请求时,服务器会返回网站的 SSL 证书,浏览器需要对证书做以下验证

  • 验证域名、有效期等信息是否正确
  • 判断证书来源是否合法
  • 判断证书是否被篡改
  • 判断证书是否已吊销

证书公开问题 虽然中间人可以得到证书,但私钥是无法获取的,一份公钥是不可能推算出其对应的私钥,中间人即使拿到证书也无法伪装成合法服务端,因为无法对客户端传入的加密数据进行解密。

HTTPS 的数据是加密的,常规下抓包工具代理请求后抓到的包内容是加密状态,无法直接查看。 组建中间人网络,而抓包工具作为中间人的代理 下 可实现https抓包

参考:https://juejin.cn/post/6844904065227292685

HTTP 缓存

强制缓存

只要浏览器判断缓存没有过期,则直接使用浏览器的本地缓存 强缓存是利用 HTTP 响应头部(Response Header)字段实现的,用来表示资源在客户端缓存的有效期

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

Cache-Control 的优先级高于 Expires。Cache-control 选项更多一些,设置更加精细,所以建议使用 Cache-Control 来实现强缓存。

实现

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

协商缓存

通过服务端告知客户端是否可以使用缓存的方式被称为协商缓存 如 请求的响应码是 304,告诉浏览器可以使用本地缓存的资源

实现

请求 If-Modified-Since 响应 Last-Modified (时间戳)

在请求头中添加 If-Modified-Since 头部,值为上次访问资源时的时间戳 服务器收到请求后发现有 If-Modified-Since 与被请求资源的最后修改时间(Last-Modified)进行对比,如果资源的最后修改时间在 If-Modified-Since 时间之前(即资源未被修改)返回 304 Not Modified 响应。否则,返回资源内容和 200 OK 响应

请求If-None-Match 响应 ETag (唯一标识)

ETag 是服务器为资源生成的唯一标识符,客户端在请求头部中将该值包含在 If-None-Match 标头中。当客户端发起请求时,它会在请求头部中包含上一次请求中服务器返回的 ETag 值。服务器接收到请求后,会将该值与当前资源的 ETag 值进行比较。如果资源没有变化返回 304,如果资源变化了返回 200。

注意

协商缓存这两个字段都需要配合强制缓存中 Cache-Control 字段(是否过期)来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求

HTTP 版本

http 1.0 (1996年)

每个请求/响应建立一个连接: 在 HTTP 1.0 中,每个请求都会建立一个新的 TCP 连接,用于发送请求和接收响应。这导致了较高的连接建立和关闭的开销。 无状态协议: HTTP 1.0 是无状态的,这意味着每个请求和响应都是独立的,服务器不会保留客户端的状态信息。 简单的请求头: 请求头和响应头的字段相对较少,功能有限。头部字段没有严格的标准,允许一些灵活性。 无内容协商: 在 HTTP 1.0 中,服务器不能根据客户端的特定能力来提供不同的内容。

http 1.1(1997年)

持久连接: HTTP 1.1 引入了持久连接(也称为 Keep-Alive),允许多个请求和响应共享一个连接,减少了连接建立和关闭的开销。 管道化: HTTP 1.1 允许在一个连接上同时发送多个请求,以提高并发性能。然而,由于一些实现问题,管道化并未在广泛使用。 虚拟主机支持: HTTP 1.1 引入了 Host 头部,使得服务器可以基于主机名来区分不同的虚拟主机。 状态管理: 引入了 Cookie 和 Set-Cookie 头部,允许服务器在客户端保留一些状态信息。 内容协商: HTTP 1.1 支持内容协商,允许服务器根据客户端能力选择合适的内容提供。 缓存控制: HTTP 1.1 增强了缓存控制的能力,引入了更多的缓存相关头部字段。

http 2.0 (2015 年)

二进制协议: HTTP/2 使用二进制格式传输数据,相较于 HTTP/1.x 中的文本格式,更高效地传输和解析数据。这有助于降低传输的数据量和延迟。 多路复用: HTTP/2 引入了多路复用技术,允许多个请求和响应在一个连接上并行进行。这消除了 HTTP/1.x 中的队头阻塞问题,提高了并发性能。 头部压缩: HTTP/2 使用 HPACK 压缩算法来压缩头部信息,减少了头部传输的开销。这对于包含大量头部信息的请求和响应特别有益。 服务器推送: HTTP/2 支持服务器推送,服务器可以在客户端请求之前主动将相关资源推送到客户端缓存中,提高页面加载速度。 优化流控制: HTTP/2 引入了流和帧的概念,允许客户端和服务器更好地控制和管理数据流。 提高安全性: HTTP/2 对传输层安全性(TLS/SSL)的要求更加严格,推动了更广泛的网站加密。 向后兼容: HTTP/2 设计时考虑了与 HTTP/1.x 的向后兼容,这意味着在网络环境中,不支持 HTTP/2 的情况下仍然可以使用 HTTP/1.x。

http 3.0 (2022年)

基于 QUIC: HTTP/3 使用 QUIC 作为其传输协议。QUIC 结合了 UDP 协议的快速连接建立和 TCP 协议的可靠传输特性,同时解决了 TCP 在不稳定网络环境下的一些问题,如队头阻塞。 连接复用和多路复用: HTTP/3 仍保留了多路复用的概念,允许在单个连接上同时进行多个请求和响应。与 HTTP/2 不同的是,HTTP/3 的连接复用是在 QUIC 层面实现的,因此更加灵活和高效。 减少延迟: 由于 QUIC 协议的快速连接建立和改进的拥塞控制机制,HTTP/3 在不稳定的网络环境下可以显著降低延迟,提高响应速度。 优化重传: QUIC 使用自定义的重传机制,可以更灵活地处理丢失的数据包,减少了不必要的重传和延迟。 兼容性和向后兼容: HTTP/3 设计时考虑了与 HTTP/1.x 和 HTTP/2 的向后兼容性,这意味着在不支持 HTTP/3 的网络环境中,可以回退到 HTTP/1.x 或 HTTP/2

quick协议 https://xiaolincoding.com/network/2_http/http3.html#quic-%E5%8D%8F%E8%AE%AE%E7%9A%84%E7%89%B9%E7%82%B9

常见状态码

2xx 表示服务器成功处理了客户端的请求。200 ok;

3xx 重定向301 永久重定向; 302 临时重定向; 304 缓存重定向

4xx 错误码,服务器无法处理; 400 客户端请求的报文有错误; 403 服务器禁止访问资源; 404 请求的资源在服务器上不存在或未找到

5xx 客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。500 通用的错误码,服务器发生了错误; 501 客户端请求的功能还不支持;502 服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误;503 表示服务器当前很忙,暂时无法响应客户端

参考链接:https://xiaolincoding.com