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

计算机网络 QA

DNS 的解析过程

  1. 浏览器缓存。当用户通过浏览器访问某域名时,浏览器首先会在自己的缓存中查找是否有该域名对应的 IP 地址(曾经访问过该域名并且没有清空缓存)
  2. 系统缓存。当浏览器缓存中无域名对应的 IP 地址时,会自动检测用户计算机系统内的 Hosts 文件中是否存在域名对应的 IP 地址
  3. 路由器缓存。当浏览器和系统缓存中均无域名对应的 IP 地址时,则会进入路由器缓存中查找(上述三步均为客户端的 DNS 缓存 )
  4. ISP(互联网服务提供商)DNS 缓存。当在用户客户端找不到域名对应的 IP 地址时,会进入 ISP DNS 缓存中查找。比如你用的是电信网络,那么就会进入电信的 DNS 缓存服务器中查找
  5. 根域名服务器。当上述均未找到时,会进入根域名服务器中查找(全球仅有 13 台根域名服务器,其中 1 个主根域名服务器,其余 12 台为辅根域名服务器),根域名服务器在收到请求后会查看区域文件记录,如果没有,则将其管辖范围内的顶级域名服务器的 IP 地址告诉本地 DNS 服务器
  6. 顶级域名服务器。顶级域名服务器在收到请求后会查看域名文件记录,如果没有,则将其管辖范围内的主域名服务器的 IP 地址告诉本地 DNS 服务器
  7. 主域名服务器。主域名服务器在收到请求后会查询自己的缓存,如果没有,则进入下一级域名服务器中进行查找,重复该步骤直到找到正确的记录
  8. 保存结果至缓存。本地域名服务器把返回的结果保存到缓存,以备下一次使用,同时将该结果反馈给客户端,客户端通过这个 IP 地址与 Web 服务器建立连接

TCP 为什么可靠?

  • 超时重传机制、快速重传机制
  • 流量控制(滑动窗口)
  • 拥塞控制

超时重传

就是在发送数据时,设定一个定时器(RTO),当超过指定的时间后,没有收到对方的 ACK 确认应答报文,就会重发该数据。该计时器的时间一般是由当前网络来决定的,一个 RTT 指的是当一个报文从发送到接收所需的时间,RTO 的取值是发送方尝试发送几个报文,然后取平均 RTT 时间来决定的。

TCP 会在以下两种情况发生超时重传:数据包丢失、确认应答丢失。

快速重传

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

当接收方发现接收到的序列号不对的时候,会发送连续的三个 ACK 标志,告诉发送方这个报文在传输过程中出现了丢包。发送方如果接收到某个相同的序列号的三个 ACK 报文,那么此时立马重发该报文,不会等待计时器的时间结束。

在这里插入图片描述

滑动窗口

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

有了窗口,就可以指定窗口大小,窗口大小就是指无需等待确认应答,而可以继续发送数据的最大值。

发送方通过维持一个发送滑动窗口来确保不会发生由于报文发送太快导致接收方无法及时处理的问题。此时发送方的报文分为四类:第一类是已经发送并且得到接收方确认的报文;第二类是已经发送但是没有接收到确认的报文;第三类是发送方还没发送,但是滑动窗口还足够巨大,允许被发送的报文;第四类是还没发送并且窗口已经被占满,不允许发送的报文。

在这里插入图片描述

流量控制

发送方不能无脑发数据给接收方,要考虑接收方的处理能力,否则就会导致触发重发机制,从而导致网络流量的无端浪费。

为了解决这种现象,TCP 提供一种机制可以让发送方根据接收方的实际接收能力,控制发送的数据量,这就是所谓的流量控制。

拥塞控制

流量控制是避免发送方的数据填满接收方的缓存,但是并不知道网络中发生了什么。

一般来说,计算机网络都处在一个共享的环境。因此也有可能会因为其他主机之间的通信使得网络拥堵。

网络出现拥堵时,如果继续发送大量数据包,可能会导致数据包时延、丢失等,这时 TCP 就会重传数据,但是一重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这个情况就会进入恶性循环,被不断地放大。

所以,TCP 不能忽略网络上发生的事,它被设计成一个无私的协议,当网络发送拥塞时,TCP 会自我牺牲,降低发送的数据量。

于是,就有了拥塞控制,控制的目的就是避免发送方的数据填满整个网络。

为了在发送方调节所要发送数据的量,定义了一个叫做拥塞窗口的概念。

拥塞窗口 cwnd (rwnd 表示接收窗口)是发送方维护的一个状态变量,它会根据网络的拥塞程度动态变化的。

拥塞控制主要是四个算法:慢启动、拥塞避免、拥塞发生、快速恢复。

在这里插入图片描述

HTTP 的状态码

  • 信息状态码:1 开头
  • 成功状态码:2 开头
  • 重定向状态码:3 开头
  • 客户端错误状态码:4 开头
  • 服务端错误状态码:5 开头
  • 200 状态码:成功获取资源(获取到服务器资源或者请求强缓存)
  • 304 状态码:请求协议缓存资源
  • 301 状态码:永久重定向,被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址,除非额外指定,否则这个响应也可缓存
  • 302 状态码:临时重定向,请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求,只有在 Cache-Control 或 Expires 中进行了指定的情况下,这个响应才是可缓存的
  • 401 状态码:未经授权,请求要求身份验证

GET 和 POST

  • GET 一般是去请求获取资源,POST 一般是发送数据到后台使用
  • GET 中的参数是拼接在 URL 后面的,不安全且长度有限制,POST 中的参数是放在 Request body 中的,相对安全且不受长度限制
  • GET 在刷新浏览器或回退时不受影响,POST 在回退时会重新提交数据请求
  • GET 请求可被缓存,POST 请求不会被缓存
  • GET 请求只能进行 URI 编码,POST 请求支持多种编码方式
  • GET 产生一个 TCP 数据包,POST 产生两个 TCP 数据包
  • 对于 GET 请求,浏览器会把 HTTP HEADER 和 DATA 一并发送出去,服务器响应 200 OK(返回数据),而对于 POST 请求,浏览器会先发送 HEADER,待服务器响应 100 CONTINUE 之后,浏览器再发送 DATA,服务器响应 200 OK(返回数据)

其他请求方法

  • GET:向指定的资源发出“显示”请求
  • POST:向指定资源提交数据,请求服务器进行处理
  • PUT:向指定资源位置上传其最新内容
  • DELETE:请求服务器删除 Request-URL 所标识的资源
  • TRACE:回显服务器收到的请求,主要用于测试或诊断
  • CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器,通常用于 SSL 加密服务器的连接

TCP/IP 和 HTTP 协议的区别?

  • TCP 处于传输层,HTTP 处于应用层
  • HTTP 是基于 TCP 协议上的一种应用
  • TCP 是底层协议,是定义数据传输和连接方式的规范
  • HTTP 是应用层协议,是定义传输数据的内容的规范

对称加密和非对称加密

  • 对称秘钥加密,又称私钥加密。即信息的发送方和接收方用同一个秘钥去加密和解密数据,它的最大优势是加/解密速度快,适合对大数据量进行加密,但秘钥管理困难
  • 非对称秘钥加密,又称公钥加密。它需要使用一对秘钥来分别完成加密和解密的操作,一个公开发布,即公开秘钥,另一个由用户自己秘密保存,即私有秘钥,信息发送者用公开秘钥去加密,而信息接收者用私有秘钥去解密
  • 从功能和安全角度而言,非对称加密比对称加密强大,但加/解密速度却比对称秘钥慢得多

HTTP 长连接和短连接的区别?

  • HTTP 协议是无状态的,无状态是指 HTTP 协议对事务处理没有记忆能力,服务器不知道客户端的状态,每次发送请求都得重新建立连接
  • HTTP/1.0 协议默认是短连接,客户端和服务器每进行一次 HTTP 请求就需要建立一次连接,结束后就中断连接,在访问网络中含有其他的 Web 资源时,每次去访问一个 Web 资源,浏览器就会新建一个 HTTP 会话
  • HTTP/1.1 协议默认是长连接,保持其连接的持续性,在使用 HTTP 长连接的时候,HTTP 对应的响应头会有 Connection: keep-alive
  • 长连接:当浏览器打开网页后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接通道不会关闭,等客户端再次访问服务器时,会继续使用已存在的连接。但是这个 Connection: keep-alive 也不会永远保持连接,保持的时间是由服务器设定的,实现长连接需要客户端和服务端都支持
  • HTTP 协议的长连接和短连接实际上是 TCP 协议的长连接和短连接

轮询、长轮询、长连接、WebSocket 的区别?

  • 轮询:客户端定时向服务器发送请求,服务器收到请求后立马返回响应信息并关闭连接。优点是后端程序编写比较容易,缺点是请求中有大半是无用的,会浪费带宽和服务器资源。这种方式由于需要不断建立 HTTP 连接,严重浪费了服务器和客户端的资源,短轮询不适合那些同时在线用户数量比较大,并且很注重性能的 Web 应用
  • 长轮询:客户端向服务器发送请求,服务器收到请求后 hold 住连接,直到有新消息返回响应信息时(或到了设定的超时时间时)才关闭连接,客户端处理完响应信息后再向服务器发送新的请求。优点是减少很多不必要的 HTTP 请求次数,相比之下节约了资源,缺点是服务器 hold 连接会消耗资源,需要同时维护多个线程,而服务器所能承受的 TCP 连接数是有上限的,这种轮询很容易把连接数占满,例如:webQQ、facebook IM
  • 长连接:HTTP/1.1 通过使用 Connection: keep-alive 进行长连接,HTTP/1.1 默认进行持久连接,在一次 TCP 连接中可以完成多个 HTTP 请求,但是每个请求仍然要单独发 HEADER
  • WebSocket:WebSocket 协议本质上是一个基于 TCP 的协议,为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发送一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,它包含了一些附加头信息,其中附加头信息 upgrade: WebSocket 表明这是一个申请协议升级的 HTTP 请求,服务器解析这些附加的头信息,然后产生响应信息返回给客户端,客户端和服务器的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由地传递信息,并且这个连接会一直持续到客户端或服务器任意一方主动关闭连接
  • 兼容性:短轮询 > 长轮询 > 长连接 > WebSocket
  • 性能:WebSocket > 长连接 > 长轮询 > 短轮询

Session、Cookie 和 Application 的区别?

  • Cookie:Cookie 存放在客户端中,因此有效时间以客户端的时间为准,可以手动设置,如果没有指定 Cookie 对象的有效期,则 Cookie 对象只存在客户端的内存,当浏览器关闭时,Cookie 就会失效,Cookie 中保存的是字符串,支持跨域名访问
  • Session:Session 是服务器技术,利用这个技术,服务器可以把与会话相关的数据写到一个代表会话的 Session 对象中,用来存储用户跨网页程序的变量,只针对单一用户,Session 的有效期可以自己设置,Session 保存的是对象,不支持跨域名访问
  • Application:多个用户共享的应用级别的作用域,在服务器,相比前两者它的存在时间最长,只有当关闭服务器时才会失效

Cookie 是如何工作的?

当客户端访问服务器时,服务器通过 Cookie 构造器构造一个 Cookie 实类,然后服务器在响应信息头中附带 Cookie 实类到客户端,并保存在客户端内存中,在 Cookie 生命周期内,以后的每次请求都会携带这个 Cookie。

Cookie 和 Session 是如何记住登录状态的?

当 Session 启动时,服务器会生成一个唯一值,称为 sessionid,服务器会开辟一块内存,对应该 sessionid,服务器再将该 sessionid 写入浏览器的 Cookie,服务器内有一进程,监视所有 Session 的活动状态,如果有 Session超时或主动关闭,服务器就释放该内存块。当浏览器请求服务器时,服务器会先查看请求头 Cookie 中是否有 seesionid,如果有,就检查该 sessionid 对应的内存是否有效,有效则读取内存中的值,无效则建立新的 Session。

当 Cookie 被禁止时,如何保存登录状态?

保存登陆状态的关键不是 Cookie,而是通过 Cookie 保存和传送 sessionid 的值,我们可以通过 encodeURL 编码 URL,或者 access token,然后将其保存到 localstorage 即可。

什么是死锁以及死锁的解决办法?

  • 死锁:是指两个或者两个以上的进程在执行过程中,由于竞争资源或者彼此通信而造成的一个阻塞现象,若无外力作用,它们都将无法继续推进下去
  • 互斥条件:进程对所分配到的资源具有排它性,即一个资源只能被一个进程所占用,直到进程被释放
  • 请求和保持条件:当进程因请求资源而进入阻塞时,对方获得的资源保持不放
  • 不剥夺条件:进程已获得的资源在未使用完之前不能被剥夺,只能在使用完时由自己释放
  • 环路等待条件:在发生死锁时,所等待的进程必定会形成一个环路(类似于死循环),造成永久阻塞
  • 解决办法:破坏任意的必要条件即可

Web 安全防范

  • XSS:跨站脚本攻击,它指的是攻击者往 Web 页面里面插入恶意代码脚本,而网站在设计输入输出部分时,没有对用户的输入内容进行过滤,当用户浏览网站时,嵌入的 Web 脚本代码就会被执行,从而达到恶意攻击用户的特殊目的。防范手段有:设置 HttpOnly,XSS 攻击主要是想获取到 Cookie 中的 sessionid 并劫持对话,而当 Cookie 设置为 HttpOnly 属性时,js 脚本将无法获取到 Cookie 信息;输入输出检查过滤;HTML 代码转译
  • CSRF:跨站请求伪造攻击,它通过伪装来自信任用户的请求来攻击信任网络,或者理解为盗用用户的身份,以用户的名义来进行某些非法操作。防范手段有:验证 HTTP Referer 字段,在 HTTP 请求头中有一个 Referer 字段,它记录了该 HTTP 请求的来源地址,只需要核对 Referer 字段是否是合法来源即可,注意在 IE6 中可以修改 Referer 值;在请求地址中添加 token,可以在 HTTP 请求中以参数加入一个随机的 token,并在服务器上建立一个拦截器来验证这个 token;在 HTTP 头中自定义属性并验证,其方法和 token 差不多,只是将其添加到 HTTP 头自定义属性中
  • SQL 注入:攻击者在 HTTP 请求中注入恶意的 SQL 代码,服务器使用参数构建数据库 SQL 命令时,恶意的 SQL 会被一起构建,从而达成某些非法的操作。防范手段有:有效性的核查和过滤;限制字符串输入长度;服务器使用预编译的 PrepareStatement

为什么浏览器会产生同源策略?

同源策略的目的是为了限制不同源的 document 或者脚本之间互相访问,以免造成干扰和混乱。如果没有限制,那么浏览器中的 Cookie 等数据就可以被任意读取,不同域下的 DOM 任意操作,ajax 任意请求其他网站的数据包括隐私数据。

浏览器的缓存机制

  • 强缓存:判断是否是缓存的依据,来自于是否超出某个时间或者某个时间段,而不关心服务器文件是否已经更新。强缓存主要分为两种: ExpiresCache-ControlExpires 保存的是一个绝对时间,即缓存过期时间,它是相对服务器时间来定的,浏览器会判断本地时间和Expires 来确定是否要访问本地缓存,由于服务器时间和客户端时间在很多时候是不相等的,所以有可能会造成不确定性,现在几乎很少使用 ExpiresCache-control 保存的是一个相对时间,可以通过设置 max-age 来确定文件的缓存时间,其原理和 Expires 一样,当两者同时存在时,Cache-Control 的优先级高于 Expires
  • 协商缓存:由服务器来确定缓存资源是否可用,协商缓存主要分为两种:Last-ModifyETagLast-Modify:浏览器第一次访问服务器的时候,会在返回的请求头中加上一个 Last-Modified 字段,它是资源的最后修改时间,当浏览器再次访问时,其请求头中会包含一个 If-Modified-Since 字段,服务器判断它是否相同再确定是返回 304 还是 200;ETag:其原理和 Last-Modify 几乎一样,只是它返回的是一般是哈希值或是对该资源的 md5 值(生成规则由服务器决定),它会在请求头携带 If-None-Match 字段,如果两者同时存在,ETag 的优先级高于 Last-ModifyLast-Modified 只能精确到秒,秒内的内容更新只有 ETag 才能检查,文件有时会定时重新生成相同的内容,Last-Modified 不能很好地识别,ETag 每次服务器生成都需要进行读写操作,而 Last-Modified 只需要读取操作,Etage 的消耗更大
  • 如果有强缓存,且强缓存未过期,浏览器会优先访问强缓存,并返回 200,在没有强缓存或者强缓存过期的情况下才会访问协商缓存,再根据 EtagLast-Modified 返回 304 或 200

在这里插入图片描述

浏览器从输入 URL 到页面渲染的过程

  1. 浏览器输入 URL 并回车
  2. 浏览器查找 URL 是否存在未过期的缓存
  3. 域名解析 URL 对象的 IP
  4. 根据 IP 和服务器建立 TCP 三次握手连接
  5. 客户端发送 HTTP 请求
  6. 服务器处理请求并返回响应报文
  7. 浏览器接收 HTTP 响应
  8. 构造 DOM 树、渲染页面
  9. 四次挥手关闭 TCP 连接

TCP 建立连接的过程

TCP/IP 三次握手

  1. 第一次握手。建立连接时,客户端发送 SYN 包(seq=x)到服务器,进入 SYNC_SEND 状态,等待服务器确认
  2. 第二次握手。服务器收到 SYN 包,必须先确认客户端的 SYN,同时服务器发送 SYN 包(ack=x+1,seq=y),进入 SYN_RECV 状态
  3. 第三次握手。客户端收到服务器的 SYN + ACK 包,并向服务器发送 ACK 确认包(ack=y+1),客户端和服务器都进入 ESTABLISHED 状态

如果建立连接之后客户端出现故障

TCP 设有一个 保活计时器,服务器在每收到一次客户端的请求后都会重置该计时器,时间通常设置为 2 小时,若 2 小时后还没有收到客户端的任何数据,服务器就会发送一个探测报文段,之后每隔 75s 再发送一次,若连续发送 10 个探测报文段都仍未有响应,那么服务器便认为客户端出现故障并主动关闭连接。

TCP/IP 四次挥手

  1. 第一次挥手。客户端发送(FIN=1,seq=u),进入 FIN-WAIT-1 状态
  2. 第二次挥手。服务器收到报文后,发送确认报文(ACK=1,ack=u+1),进入 CLOSE_WAIT 状态
  3. 第三次挥手。服务器发送(FIN,seq=w)用来关闭客户端与服务器之间的数据传送,进入 LAST_ACK 状态
  4. 第四次挥手。客户端收到 FIN 包后进入 TIME_WAIT 状态,并发送 ACK 确认报文(ack=w+1)给服务器,服务器接收后进入 CLOSED 状态,完成四次挥手

为什么客户端发送完最后一个 ACK 包后并不会立刻进入 CLOSED 状态,而是会等待 2MSL(最长报文段寿命)

如果网络是不可靠的,那么有可能最后一个 ACK 会丢失,而服务器将会不断重复地发送 FIN 片段,所以客户端不能立即关闭,它必须确认服务器已经接收到了该 ACK,TIME_WAIT 状态就是用来重发可能丢失的 ACK 报文,客户端会设置一个计时器并等待 2MSL 的时间,如果在该时间内再次收到 FIN,那么客户端就会重新发送一个 ACK 并再次等待 2MSL。所谓的 MSL就是一个片段在网络中的最大存活时间,2MSL 就是发送和回复所需要的最大时间,如果直到 2MSL 时间后客户端都没有再次收到 FIN,那么客户端就判断 ACK 已经被成功接收并结束 TCP 连接。

为什么要三次握手

主要是为了防止失效的连接请求报文段被服务器接收,从而产生错误,如果建立连接只需要两次握手,客户端没有太大改变,还是需要获得服务器的响应后才进入 ESTABLISHED 状态,而服务器则是在接收到连接请求后就进入 ESTABLISHED 状态。此时如果网络阻塞导致客户端发送的连接请求迟迟不到服务器,客户端便会超时重发,这时如果服务器正确接收并响应了,双方便开始通信,通信结束后释放连接。此时如果那个失效的连接请求抵达了服务器,由于只存在两次握手,那么服务器就会再次进入 ESTABLISHED 状态,等待发送数据或主动发送请求,但此时客户端已经进入 CLOSED 状态,那么服务器就会一直等待下去,浪费连接资源。

为什么要四次挥手

四次挥手中的第二次和第三次是分开的,而不是像三次握手那样一起发送,因为服务器发送报文段二的时候只是确认客户端发送的结束报文,并不代表自身的数据已经传输完毕,由于时间是不确定的,如果硬是等到自身数据传输完毕后再将确认报文 ACK 和自身结束报文 FIN 一起发送,可能会导致客户端超时重传等问题,造成资源浪费。

什么是线程,线程和进程的区别?

  • 进程和线程都是一个时间段的描述,是 CPU 工作时间段的描述,它们只是颗粒大小不同
  • 进程是资源分配和调度的一个独立单位,而线程是 CPU 调用的基本单位
  • 同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进程至少包括一个线程
  • 进程的创建调用 fork 或者 vfork,而线程创建调用 pthread_create,进程结束后它拥有的所有线程都将销毁,而线程结束不会影响同个进程中的其他线程
  • 线程是轻量级的进程,它的创建和销毁所需的时间比进程小很多,操作系统中所有的执行功能都是创建线程去完成的
  • 线程中执行时一般都要进行同步和互斥,因为它们共享同一进程的所有资源
  • 线程有自己的私有属性:TCB、线程 id、寄存器、硬件上下文,而进程也有自己的私有属性:进程控制块 PCB,这些私有属性是不被共享的,是一个进程或一个线程的标志

let、const 和 var 的区别?

  • var 声明的变量会挂载在 window 上,而 let 和 const 声明的变量不会
  • var 声明的变量存在变量提升,let 和 const 不存在变量提升
  • let 和 const 声明形成块状作用域
  • 同一作用域下,let 和 const 不能声明同名变量,而 var 可以
  • const 一旦声明必须赋值,且声明后不能修改,如果声明的是复合类型数据,则可以修改其属性

介绍一下 promise 相关的东西

  • pedding、fulfilled、rejected(未决定、履行、拒绝),同一时间只能存在一种状态,且状态一旦改变就不能再变
  • 初始化,状态:pedding
  • 当调用 resolve(成功),状态:pedding -> fulfilled
  • 当调用 reject(失败),状态:pedding -> rejected

js 判断类型的方法

  • typeof:只能判断基本数据类型,判断引用类型都是 object
  • instanceof:只能进行类型的对比,不能进行类型的判断,测试后者是否是前者的原型链上的构造函数
  • Object.prototype.toString.call(arr):能较为准确判断数据类型,测试该该对象是否是括号中函数的原型

New 一个对象的过程

  1. 创建一个空对象 obj
  2. 将 obj 的 prototype 属性指向构造函数原型(prototype)
  3. 将构造函数内部的 this 绑定在新对象 obj 上,执行构造函数(用 apply 方法绑定 this)
  4. 若构造函数没有返回其他对象,则返回该新建的 obj,否则返回引用类型的值

原型链

  • _proto_ 属性(隐式原型):它的值就是它所对应的原型对象,作用是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的 _proto_ 属性所指向的那个对象里找,一直向上找直到 _proto_ 属性的终点 null,再往上找相当于在 null 上取值,会报错,通过 _proto_ 属性将对象连接起来的这条链路即我们所说的原型链
  • Prototype 属性(显示原型):是函数的原型对象,作用就是让该函数所实例化的对象们可以找到公用的属性和方法
  • Constructor 属性:是指向该对象的构造函数,所有函数的最终构造函数都是 Function

JSON.parse(JSON.stringify()) 深拷贝的弊端

  • JSON.parse(JSON.stringify()) 实现深拷贝,其原理就是利用 JSON.Stringify 将 js 对象序列化,再反序列化还原对象,序列化的作用是存储(对象本身存储的只是一个地址映射,如果断电则对象将不复存在,因此需要将对象的内容转换成字符串的形式再保存在磁盘上)和传输
  • 如果 obj 里面有时间对象,用其处理后返回的只是字符串形式的数据
  • 如果 obj 里有 RegExp、Error 对象,则序列化的结果会变成空对象
  • 如果 obj 里有函数、undefined,则序列化的结果会把函数或 undefined 丢失
  • 如果 obj 里有 NaN、Infinity 和 -Infinity,则序列化的结果会变成 null
  • JSON.stringify 只能序列化可枚举的自由属性,例如:如果 obj 中的对象是由构造函数生成的,则实行深拷贝后会丢失对象的 constructor
  • 如果对象中存在循环引用的情况也无法正确实现深拷贝

深拷贝

使用递归的方式实现深拷贝

function deepClone1(obj) {// 判断要进行深拷贝的是数组还是对象, 是数组的话进行数组拷贝, 对象的话进行对象拷贝var objClone = Array.isArray(obj) ? [] : {};if (obj && typeof obj === "object") {for (key in obj) {if (obj.hasOwnProperty(key)) {if (obj[key] && typeof obj[key] === "object") {objClone[key] = deepClone1(obj[key]);} else {objClone[key] = obj[key];}}}}return objClone;
}

通过 JSON 对象实现深拷贝

var _obj = JSON.parse(JSON.stringify(obj))

通过 Jquery 的 extend 方法实现深拷贝

$.extent(true, {}, obj);

通过 Object.assign() 拷贝

// 当对象中只有一级属性没有二级属性的时,此方法为深拷贝, 但是对象中有对象的时候, 此方法在二级属性以后就是浅拷贝
var _obj = Object.assign({}, obj); 

Lodash 函数库实现深拷贝

_.CloneDeep()

两个对象比较

function diff(val1, val2) {var o1 = val1 instanceof Object;var o2 = val2 instanceof Object;if (!o1 || !o2) {return val1 === val2;}if (Object.keys(val1).length !== Object.keys(val2).length) {return false;}for (var o in val1) {var t1 = val1[o] instanceof Object;var t2 = val2[o] instanceof Object;if (t1 && t2) {diff(t1, t2)} else if (val1[o] !== val2[o]) {return false;}}return true;
}

HTTPS 的工作流程

  1. 客户端(浏览器)访问 https://www.baidu.com 百度网站
  2. 百度服务器返回 HTTPS 使用的 CA 证书
  3. 浏览器验证 CA 证书是否为合法证书
  4. 验证通过,证书合法,生成一串随机数并使用公钥(证书中提供的)进行加密
  5. 发送公钥加密后的随机数给百度服务器
  6. 百度服务器拿到密文,通过私钥进行解密,获取到随机数(公钥加密,私钥解密,反之也可以)
  7. 百度服务器把要发送给浏览器的内容,使用随机数进行加密后传输给浏览器
  8. 此时浏览器可以使用随机数进行解密,获取到服务器的真实传输内容。

这就是 HTTPS 的基本运作原理,使用对称加密和非对称机密配合使用,保证传输内容的安全性。

相关文章:

计算机网络 QA

DNS 的解析过程 浏览器缓存。当用户通过浏览器访问某域名时,浏览器首先会在自己的缓存中查找是否有该域名对应的 IP 地址(曾经访问过该域名并且没有清空缓存)系统缓存。当浏览器缓存中无域名对应的 IP 地址时,会自动检测用户计算机…...

安果天气预报 产品介绍

软件介绍版本号 2.0.5 安果天气预报:全世界覆盖,中国定制 想要查找北京、上海、纽约、东京还是巴黎的天气?一款简约的天气预 报应用为你呈现。专注于为用户提供纯净的天气体验,我们不发送任何打扰的通知。包含空气质量、能见度、…...

net start Mysql 启动服务时 ,显示“Mysql服务正在启动 Mysql服务无法启动 服务没有报告任何错误

一、问题 有时候,输入net start Mysql 启动服务时 mysql>net start Mysql 显示 Mysql服务正在启动 Mysql服务无法启动 服务没有报告任何错误 二、原因 由于mysql的默认端口是3306,因此在启动服务的时候,如果此端口被占用,就会出…...

DAY24

题目一 啊 看着挺复杂 其实很简单 第一种方法 就是纵轴是怪兽编号 横轴是能力值 看看能不能打过 逻辑很简单 看看能不能打得过 打过的就在花钱和直接打里面取小的 打不过就只能花钱 这种方法就导致 如果怪兽的能力值很大 那么我们就需要很大的空间 所以引出下一种做法 纵…...

Redis过期数据的删除策略

1 介绍 Redis 是一个kv型数据库,我们所有的数据都是存放在内存中的,但是内存是有大小限制的,不可能无限制的增量。 想要把不需要的数据清理掉,一种办法是直接删除,这个咱们前面章节有详细说过;另外一种就是…...

如何使用CSS实现一个拖拽排序效果?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 实现拖拽排序效果的CSS和JavaScript示例⭐ HTML 结构⭐ CSS 样式 (styles.css)⭐ JavaScript 代码 (script.js)⭐ 实现说明⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦…...

leetcode 118.杨辉三角

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;https://leetcode.cn/problems/pascals-triangle/description/ 代码&#xff1a; class Solution { public:vector<vector<int>> generate(int numRows) {// 先开空间vector<vector<int>> v;v.…...

微服务框架之SpringBoot面试题汇总

微服务框架之SpringBoot面试题汇总 什么是Spring Boot&#xff1f; 多年来&#xff0c;随着新功能的增加&#xff0c;spring变得越来越复杂。Spring项目&#xff0c;我们必须添加构建路径或添加Maven依赖关系&#xff0c;配置应用程序服务器&#xff0c;添加spring配置。因此&…...

Promise详解

目录 一、前言&#xff1a;为什么会出现Promise?二、Promise是什么?2.1 Promise的初体验 三、使用Promise的好处?3.1 指定回调函数的方式更加灵活3.2 可以解决回调地狱问题&#xff0c;支持链式调用 四、Promise实例对象的两个属性五、resolve函数以及reject函数六、Promise…...

Oracle 查询(当天,月,年)的数据

Trunc 在oracle中&#xff0c;可利用 trunc函数 查询当天数据&#xff0c;该函数可用于截取时间或者数值&#xff0c;将该函数与 select 语句配合使用可查询时间段数据 查询当天数据 --sysdate是获取系统当前时间函数 --TRUNC函数用于截取时间或者数值&#xff0c;返回指定的…...

什么是梯度下降

什么是梯度下降 根据已有数据的分布来预测可能的新数据&#xff0c;这是回归 希望有一条线将数据分割成不同类别&#xff0c;这是分类 无论回归还是分类&#xff0c;我们的目的都是让搭建好的模型尽可能的模拟已有的数据 除了模型的结构&#xff0c;决定模型能否模拟成功的关键…...

开黑啦kook 机器人开发 PHP swoole Liunx 服务器(宝塔)

安装环境 PHP 拓展 直接使用 宝塔一键安装 &#xff08;Windows系统不支持&#xff09; 设置命令行的PHP版本避免执行脚本时 获取不到 swoole 检查swoole是否安装成功 获取官方SDK GitHub - kaiheila/php-bot: 开黑啦机器人的php版本https://github.com/kaiheila/php-bot 配…...

Vue 中hash 模式与 history 模式的区别

hash 模式&#xff1a; - 地址中永远带着 # 号&#xff0c;不美观。 - 兼容性比较好。 - 通过手机 app 分享地址时&#xff0c;如果 app 效验严格&#xff0c;该地址会被标记为不合法。 history 模式&#xff1a; - 地址干净&#xff0c;美观。 - 兼容性和 hash 模式相比…...

Dockerfile推送私有仓库的两个案例

一&#xff0c;编写Dockerfile制作Web应用系统nginx镜像&#xff0c;生成镜像nginx:v1.1&#xff0c;并推送其到私有仓库。 具体要求如下&#xff1a; &#xff08;1&#xff09;基于centos基础镜像&#xff1b; &#xff08;2&#xff09;指定作者信息&#xff1b; &#xff…...

【指标】指标公式大全,款款经典(建议珍藏)!-神奇指标网

三、指标源码&#xff1a; 1、连续三天高开高走的选股公式 count(o〉ref(c,1&#xff09;andc>o&#xff0c;3)3&#xff1b; 2、连续3天每天的最低价都比前一天高 count&#xff08;l〉ref(c,1&#xff09;,3)3&#xff1b; 3、周量缩小50%或40&#xff05;或n&#x…...

面试题目收集

Zset排行榜功能如何设计key&#xff1f; key就设计成排行榜的名字&#xff0c;比如下面插入或者更新数据 Long zadd(final String key, final double score, final String member) key : 排行榜的名字 memeber : 用户 score : 用户的分数 项目…...

创建R包-2.1:在RStudio中使用Rcpp制作R-Package(更新于2023.8.23)

目录 0-前言 1-在RStudio中创建R包项目 2-创建R包 2.1通过R函数创建新包 2.2在RStudio通过菜单来创建一个新包 2.3关于R包创建的说明 3-添加R自定义函数 4-添加C函数 0-前言 目标&#xff1a;在RStudio中创建一个R包&#xff0c;这个R包中包含C函数&#xff0c;接口是Rc…...

chatGPT如何解释泽众PerformanceRunner性能测试工具?

PerformanceRunner 是一个性能测试工具&#xff0c;可以帮助测试人员进行性能测试。它的主要功能包括&#xff1a; 1. 脚本录制和回放&#xff1a; PerformanceRunner可以录制 HTTP/HTTPS 通信协议的脚本&#xff0c;并能够回放模拟真实用户的行为。通过录制和回放&#xff0c…...

LA@向量组线性相关性

文章目录 向量组线性相关性线性相关线性无关多向量向量组线性相关单向量向量组的线性相关性单位向量向量组线性相关性双向量向量组的线性相关性双向量线性相关的几何意义三向量线性相关的几何意义包含零向量的向量组线性相关概念迁移:线性方程组和线性相关齐次线性方程组和向量…...

[k8s] 基于ubuntu22部署k8s1.28记录

k8s1.28部署已经不依赖docker了&#xff0c;所以不需要安装docker。同理&#xff1a;如果想查看镜像和运行容器&#xff0c;也不能用docker命令去查询了&#xff1a;需要使用crictl。不过crictl命令参数兼容docker&#xff0c;所以使用上手没有啥难度。 1. 配置安装源 根据k8…...

React 事件代理 和原生事件绑定混用:你的选择会导致什么问题?

在React开发中&#xff0c;事件处理是一个常见的任务。React提供了一个方便的事件系统&#xff0c;但有时我们可能会在React组件中与原生DOM事件一起使用。本文将讨论React的事件代理机制与原生事件绑定混用可能导致的一些问题。 React的事件代理 React采用了一种称为"事…...

使用阿里云国外和国内云服务器有什么注意事项?

使用阿里云的国外和国内云服务器时&#xff0c;有一些注意事项需要考虑&#xff1a; 地理位置&#xff1a;选择离你的用户或数据中心最近的地理位置&#xff0c;可以减少延迟和提高访问速度。对于国内用户&#xff0c;使用国内云服务器可能更好&#xff1b;对于国外用户&#…...

【计算机网络】【常考问题总结】

1. ping 127.0.0.1 后会发生什么&#xff1f; ping 127.0.0.1 &#xff1b;ping 0.0.0.0 &#xff1b; ping localhost 面试官问&#xff1a;断网了&#xff0c;还能ping通 127.0.0.1 吗&#xff1f;为什么&#xff1f;_kevin_tech的博客-CSDN博客 2. MTU&#xff0c;MMU是…...

前端基础(props emit slot 父子组件间通信)

前言&#xff1a;如何实现组件的灵活使用&#xff0c;今天学习组件封装用到的props、slot和emit。 目录 props 子组件 父组件 示例代码 slot 示例代码 作用域插槽 emit 示例代码 props 需要实现在其他组件中使用同一个子组件。 子组件 子组件&#xff08;所谓子组件…...

即时通讯:短轮询、长轮询、SSE 和 WebSocket 间的区别

在现代 Web 开发中&#xff0c;即时通讯已经成为许多应用程序的重要组成部分。为了实现即时通讯&#xff0c;开发人员通常使用不同的技术和协议。本文将介绍四种常见的即时通讯实现方法&#xff1a;短轮询、长轮询、SSE&#xff08;服务器发送事件&#xff09;和 WebSocket&…...

高忆管理:药店零售概念回落,开开实业走低,此前7日大涨超80%

药店零售概念18日盘中大幅下挫&#xff0c;到发稿&#xff0c;华人健康跌逾11%&#xff0c;漱玉布衣、塞力医疗跌超9%&#xff0c;重药控股、浙江震元、榜首医药等跌超7%&#xff0c;药易购跌超6%&#xff0c;开开实业跌超3%。 值得注意的是&#xff0c;开开实业此前7个交易日斩…...

Go1.19 排序算法设计实践 经典排序算法对比

详解经典排序算法 01 为什么要学习数据结构与算法 抖音直播排行榜功能 案例 规则&#xff1a;某个时间段内&#xff0c;直播间礼物数TOP10房间获得奖励&#xff0c;需要在每个房间展示排行榜解决方案 •礼物数量存储在Redis-zset中&#xff0c;使用skiplist使得元素整体有序 •…...

3:Ubuntu上配置QT交叉编译环境并编译QT程序到Jetson Orin Nano(ARM)

1.Ubuntu Qt 配置交叉编译环境 1.1 ubuntu 20.04安装Qt sudo apt-get install qtcreator 1.2 配置QT GCC配置同上 最后配置Kits 上面设置完成之后 &#xff0c;设置Kits 中的Device(这是为了能够直接把项目部署到arm设备上) 点击NEXT之后会出现连接被拒绝&#xff0c;不用担…...

CentOS下MySQL的彻底卸载的几种方法

这里我为大家详细讲解下“CentOS下MySQL的彻底卸载的几种方法”的完整攻略。 前言 先通过下列命令找到需要删除的相关文件 rpm -qa mysql* whereis mysql find / -name mysql 需要上传的命令介绍 删除 MySQL 数据目录 rm -rf /var/lib/mysql 删除配置文件 rm -rf /etc/my.cnf…...

Spring 的异常处理机制

Spring 的异常处理机制 ​ 在Spring中&#xff0c;异常处理是一个非常重要的方面&#xff0c;用于捕获和处理应用程序中可能出现的异常情况。Spring提供了多种方式来处理异常。 ​ 使用Spring的异常处理机制主要有以下优点&#xff1a; ​ **统一的异常处理&#xff1a;**通…...

有商家免费建商城的网站吗/公司官网搭建

作者&#xff1a;Lemon来源&#xff1a;Python数据之道介绍一本零基础入门Python数据分析的书有不少读者在询问如何入门Python、如何入门Python数据分析&#xff0c;之前跟大家分享了两本零基础入门Python的书籍&#xff1a;《Python编程从入门到实践》 和《笨办法学Python3》。…...

做网站每年运营要花掉多少钱/如何搜索网页关键词

算法练习篇之&#xff1a;从尾到头打印链表题目描述解题思路图示代码实现总结题目描述 输入一个链表的头结点&#xff0c;从尾到头反过来打印出每个结点的值。 解题思路 题目意图十分明确&#xff0c;将一个链表从尾部依次向前打印元素&#xff0c;我们需要用一种结构从尾部…...

wordpress 固定链接 nginx/营销型网站的推广方法

目录 网络节点的性质网络的性质网络层次性评价动态网络演化——随机图模型动态网络演化——有偏好的交友模型 如果在一个企业中&#xff0c;人员通常各司其职&#xff0c;一个员工听命于一个上司&#xff0c;这样会让企业命令传达的更加清晰有效&#xff0c;如果一个员工听命…...

做调研用到的大数据网站/如何网络推广新产品

一.需求 需求如题. 当多个客户端连接服务器时,服务器如何给指定的客户端发送消息. 二.解决方案 核心思想: 在服务器端,需保存不同客户端的socket列表及客户端相关信息. socket含有发送方和接收方的ip和端口号,所以通过socket就能向指定的客户端发送消息. 经查阅资料,得到如…...

品牌网站建设完善大蝌蚪/做网站推广公司

今天公司要求研究一下python日志相关的信息&#xff0c;用户通过使用图形化界面产生错误后并不知道为什么报错。因此&#xff0c;要通过日志实现记录错误的功能。 import functools import loggingdef create_logger():logger logging.getLogger("test_log")logger…...

房产网站搭建/大数据营销成功案例

ip 是个指令喔&#xff01;并不是那个 TCP/IP 的 IP 啦&#xff01;这个 ip 指令的功能可多了&#xff01;基本上&#xff0c;他就是整合了 ifconfig 与 route 这两个指令啰&#xff5e;不过&#xff0c; ip 可以达成的功能却又多更多&#xff01;真是个相当厉害的指令。如果你…...