第二十三天


(题目来源: 前端每日知识3+1)

Javascript题目

写一个方法判断字符串是否为回文字符串

解题思路

解答过程

  1. function reverseStr(str) {
  2. // let newStr = [...str].reverse().join('')
  3. let newStr = str.split('').reverse().join('')
  4. return str == newStr ? true : false
  5. }
  6. console.log(reverseStr('abcba'));
  1. function reverseStr(str) {
  2. // let n = 0;
  3. // let len = str.length % 2 == 0 ? str.length / 2 : Math.ceil(str.length / 2) // 判断字符长度的奇偶性,从中间分开,奇数则循环它的长度-1/2 向上取整
  4. // for (let i = str.length - 1; i >= len; i--) {
  5. // console.log(`第${n+1}次循环`); // 循环的次数
  6. // if (str[i] !== str[n++]) {
  7. // return false
  8. // }
  9. // }
  10. if (str.length == 1) return true
  11. let len = str.length % 2 == 0 ? str.length / 2 : Math.floor(str.length / 2) // 判断字符长度的奇偶性,从中间分开,奇数则循环它的长度-1/2 向下取整
  12. for (let i = 0; i < len; i++) {
  13. console.log(`第${i + 1}次循环`); // 循环的次数
  14. if (str[i] !== str[str.length - 1 - i]) {
  15. return false
  16. }
  17. }
  18. return true
  19. }
  20. console.log(reverseStr('aababaa')); // true 循环了3次

知识扩展

输入url地址到页面成功渲染中间过程经历了什么

  • 大致分为几个过程
  1. url输入
  2. DNS解析
  3. TCP连接
  4. 发送Http请求
  5. 服务器处理请求
  6. 服务器响应请求
  7. 浏览器渲染页面
  8. 连接结束

url输入

  • url中文名统一资源定位符(uniform resource locator), 主要组成部分:protocol(协议), hostname(主机名), port(端口号), params(参数), query(查询), fragement(信息片段)

DNS解析

  • 主要功能就是实现ip地址的转换, 它是域名和ip地址相互映射的分布式数据库
  • 查询方式有两种: 递归查询, 迭代查询
  • DNS空间的组织方式:. 根域 .com顶级域 mr90.top 第二层域 u.mr90.top子域名 h1.u.mr90.top 主机名
  • DNS优化: 存在着多级缓冲, 浏览器缓冲, 系统缓冲, 路由器缓冲, IPS服务器缓冲, 根域名服务器缓冲, 顶级域名服务器缓冲, 主域名服务器缓冲; DNS负载均衡 使用多个IP地址, 针对不同端的请求, 服务器返回的解析结果也不同

TCP连接

  1. SYN(synchronous建立联机)
  2. ACK(acknowledgement 确认)
  3. PSH(push传送)
  4. FIN(finish结束)
  5. RST(reset重置)
  6. URG(urgent紧急)
  • 期间经历了三次握手

    1. 第一次握手:client向server发送请求,将标志位SYN置为一随机生成一个seq=x,客户端进入了SYN_SEND状态
    2. 第二次握手:server在接受到请求后,将server端的标志位SYN和ACK都设置为1, ack=x+1也就是客户端第一次握手生成的seq值,服务端然后在随机的生成一个seq值y,并将确认信息向client端发送,此时服务端进入SYN_RCVD状态
    3. 第三次握手:客户端接收到请求后先判断服务端发送的标志位ack的值是否等于x+1,服务端检查客户端发来的标志位ack是否等于y+1,和ACK的值是否等于1;如果都相同,客户端和服务器都进入established状态

题目:写一个方法判断字符串是否为回文字符串 - 图1

为什么是三次握手而不是两次

  • TCP/IP 协议是传输层的一个面向连接的安全可靠的一个传输协议, 三次握手的机制是为了保证能建立一个安全可靠的连接, 那么第一次握手是由客户端发起, 客户端会向服务端发送一个报文, 在报文里面: SYN标志位置为1, 表示发起新的连接. 当服务端收到这个报文之后就知道客户端要和我建立一个新的连接, 于是服务端就向客户端发送一个确认消息包, 在这个消息包里面:ack标志位置为1, 表示确认客户端发起的第一次连接请求. 以上两次握手之后, 对于客户端而言: 已经明确了我既能给服务端成功发消息, 也能成功收到服务端的响应. 但是对于服务端而言: 两次握手是不够的, 因为到目前为止, 服务端只知道一件事, 客户端发给我的消息我能收到, 但是我响应给客户端的消息, 客户端能不能收到我是不知道的. 所以, 还需要进行第三次握手, 第三次握手就是当客户端收到服务端发送的确认响应报文之后, 还要继续去给服务端进行回应, 也是一个ack标志位置1的确认消息. 通过以上三次连接, 不管是客户端还是服务端, 都知道我既能给对方发送消息, 也能收到对方的响应. 那么, 这个连接就被安全的建了

发送http请求

  • 完整的请求信息主要有三部分: 请求地址(协议), 请求头, 请求正文
  • 请求正文和请求头之间是一个空行

服务器处理请求

  • 后端在固定的端口接收到请求报文后, 对TCP连接进行处理, 对HTTP协议进行解析 并将报文格式转换成HTTP Request对象

题目:写一个方法判断字符串是否为回文字符串 - 图2

服务器响应请求

  • 与http请求类似, 也是由三部分组成 状态行, 响应头, 响应正文

题目:写一个方法判断字符串是否为回文字符串 - 图3

浏览器渲染页面

五个部分组成: 根据html解析 DOM树 , 根据css生成 css规则树 , 结合 DOM树css规则树 生成 渲染树 , 根据渲染树 计算 每一个 节点信息 (布局), 根据计算好的信息在 绘制 页面

  • html解析DOM树: 按照HTML的结构, 采用深度优先遍历的方式构建DOM树, 就是构建当前节点的所有子节点, 然后在构建下一个兄弟节点; 当遇到script标签时, 暂停页面的解析, 加载js执行完成后, 再次开始解析HTML构建DOM树
  • 根据css生成css规则树: 在解析css规则树时js执行将暂停, 直到css规则树构造完成, 此时页面并未进行渲染
  • 生成渲染树: DOM树和css规则树准备完成, 开始构建渲染树
  • 计算每一个节点的信息(布局): 通过构建好的渲染树信息, 计算出渲染对象的位置以及尺寸; 如果在此过程中 由于某个部分导致页面布局变化, 则需要执行重排/回流reflow操作
  • 绘制页面: 在绘制阶段系统会遍历呈现树, 调用呈现器”paint”方法将内容呈现到屏幕中, 并再此过程中执行repaint和reflow操作

连接结束

  • TCP四次挥手, 四次挥手即终止TCP连接, 就是指断开一个TCP连接时, 需要客户端和服务端总共发送4个包以确认连接的断开. 在socket编程中, 这一过程由客户端或服务端任一方执行close来触发. 由于TCP连接是全双工的, 因此, 每个方向都必须要单独进行关闭, 这一原则是当一方完成数据发送任务后, 发送一个FIN来终止这一方向的连接, 收到一个FIN只是意味着这一方向上没有数据流动了, 即不会再收到数据了, 但是在这个TCP连接上仍然能够发送数据, 直到这一方向也发送了FIN. 首先进行关闭的一方将执行主动关闭, 而另一方则执行被动关闭.
  • 关闭请求可以是客户端发起也可以是服务器端发起
  • 第一次挥手: 由客户端主动发起, 发送标志位FIN=1表示提醒服务器要关闭数据传送了, 发送序列号 随机seq=x, 进入FIN_WAIT_1状态
  • 第二次挥手: 由服务端接受到请求报文后, 自动返回一个ACK=1, ack=x+1, 进入CLOSE_WAIT状态, 客户端自动进入FIN_WAIT_2状态
  • 第三从挥手: 当服务器确认数据已发送完成 然后向客户端发送FIN报文, 生成随机序列seq=y 服务器端进入LAST_ACK状态.
  • 第四次挥手: 客户端接收FIN=1发送ack=y+1后进入TIME_WAIT状态 则可以断开连接, 客户端等待2MSL后没有收到任何的回复说明 服务器端已正常关闭, 客户端也可以关闭了

四次挥手: 四次挥手也是客户端发起的, 客户端会发送一个报文, 报文FIN=1, 当客户端收到这个报文之后, 就知道了客户端想要和我断开连接, 但是此时服务端不一定做好准备, 因为当客户端发起断开连接的报文的时候, 服务端有可能还有未发送完的报文消息需要继续发送, 所以此时服务端只能告诉客户端我知道你要和我断开连接了, 但是我这里可能还没做好准备, 需要等我一下, 等会我会告诉你, 于是, 发完这个消息确认报之后, 稍过片刻之后服务端继续发送一个断开连接的报文, FIN=1, 表明服务端已经做好断开连接的准备, 那么, 当这个消息发给客户端的时候, 客户端同样需要继续发送一个消息确认的报文, 那么通过这四次的相互沟通和连接, 我就知道了, 不管是客户端还是服务端, 都已经做好了断开的准备. 这是我对三次握手四次挥手的理解.

题目:写一个方法判断字符串是否为回文字符串 - 图4

Wireshark图解TCP三次握手与四次挥手
TCP传输过程详解——三次握手、四次挥手