[回炉计划]当输入xxxxhub的时候,竟然是这样

前言

回炉计划第三篇,这是一个经典的前端面试题,考察范围很是的广,可深刻的角度也很是的多。本篇文章的目的主要是回顾,因此内容和网络上流传的文章会有必定的重叠性。css

过程

过程大体分为如下几个步骤html

  1. DNS 解析
  2. TCP 链接
  3. 发送 HTTP 请求
  4. 服务器处理请求并返回 HTTP 报文
  5. 浏览器解析渲染页面
  6. 链接结束

DNS 解析

DNS 服务和 HTTP 协议同样,都是位于应用层的协议,它提供域名到 ip 地址之间的解析服务。 以查询www.baidu.com的 ip 地址为例前端

  1. 浏览器搜索本身的 DNS 缓存(维护一张域名与 IP 地址的对应表)
  2. 搜索操做系统中的 DNS 缓存(维护一张域名与 IP 地址的对应表)
  3. 搜索操做系统的 hosts 文件( Windows 环境下,维护一张域名与 IP 地址的对应表
  4. 操做系统将域名发送至 LDNS(本地区域名服务器,若是你在学校接入互联网,则 LDNS 服务器就在学校,若是经过电信接入互联网,则 LDNS 服务器就在你当地的电信那里。)LDNS 查询本身的 DNS 缓存(通常查找成功率在 80% 左右),查找成功则返回结果,失败则发起一个迭代 DNS 解析请求;
    1. LDNS 向 Root Name Server (根域名服务器,其虽然没有每一个域名的的具体信息,但存储了负责每一个域,如 com、net、org 等的解析的顶级域名服务器的地址)发起请求,此处,Root Name Server 返回 com 域的顶级域名服务器的地址;
    2. LDNS 向 com 域的顶级域名服务器发起请求,返回 baidu.com 域名服务器地址;
    3. LDNS 向 baidu.com 域名服务器发起请求,获得 www.baidu.com 的 IP 地址;
  5. LDNS 将获得的 IP 地址返回给操做系统,同时本身也将 IP 地址缓存起来
  6. 操做系统将 IP 地址返回给浏览器,同时本身也将 IP 地址缓存起来
  7. 至此,浏览器已经获得了域名对应的 IP 地址

补充:域名和 url 是两个概念,域名是用来确认服务器的地址的,而 url 是用来确认资源的地址;域名和 ip 地址不是一一对应的,一个域名同一时刻只能解析出一个 ip 地址,而一个 ip 地址能够绑定多个域名html5

TCP 链接

这就涉及到著名的 http 三次握手。简单来讲与服务器创建链接须要经历如下三个过程。web

  1. 第一次握手:创建链接时,客户端发送 syn 包(syn=j)到服务器,并进入 SYN_SEND 状态,等待服务器确认;
  2. 第二次握手:服务器收到 syn 包,必须确认客户的 synack=j+1),同时本身也发送一个 SYN 包(syn=k),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态;
  3. 第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK(ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手。

这里能够延申拓展一下 HTTPS 的知识 HTTPS 详解--segmentfault面试

服务器处理请求并返回 HTTP 报文

这一步主要是后端从接口获取到 tcp 报文,处理以后返回HTTP Request对象,也就是响应报文。编程

HTTP 响应报文也是由三部分组成: 状态码, 响应报头和响应报文。segmentfault

状态码由三位数字组成,表示响应的类型。状态码有五大类 1xx,2xx,3xx,4xx,5xx后端

  • 1xx:指示信息–表示请求已接收,继续处理。
  • 2xx:成功–表示请求已被成功接收、理解、接受。
  • 3xx:重定向–要完成请求必须进行更进一步的操做。
  • 4xx:客户端错误–请求有语法错误或请求没法实现。
  • 5xx:服务器端错误–服务器未能实现合法的请求。

HTTP 状态码-菜鸟编程浏览器

响应报头 HTTP 请求头提供了关于请求,响应或者其余的发送实体的信息。 HTTP 响应头信息-菜鸟编程

响应报文:就是服务器返回给浏览器的文本信息了,包括 html,js,css 等资源

浏览器解析渲染页面

浏览器拿到响应报文以后,开始解析报文并呈现网页。因为不一样的浏览器引擎实现的方法可能不一致,咱们以webkit内核为例进行说明。 WebKit 渲染的过程大体分为四步 浏览器的工做原理:新式网络浏览器幕后揭秘

构建 dom 树 -> 构建 render 树 -> 布局 render 树 -> 绘制 render 树

呈现引擎将开始解析 HTML 文档,并将各标记逐个转化成“内容树”上的 DOM 节点。同时也会解析外部 CSS 文件以及样式元素中的样式数据。HTML 中这些带有视觉指令的样式信息将用于建立另外一个树结构:呈现树。

呈现树包含多个带有视觉属性(如颜色和尺寸)的矩形。这些矩形的排列顺序就是它们将在屏幕上显示的顺序。

呈现树构建完毕以后,进入“布局”处理阶段,也就是为每一个节点分配一个应出如今屏幕上的确切坐标。下一个阶段是绘制 - 呈现引擎会遍历呈现树,由用户界面后端层将每一个节点绘制出来。

须要着重指出的是,这是一个渐进的过程。为达到更好的用户体验,呈现引擎会力求尽快将内容显示在屏幕上。它没必要等到整个 HTML 文档解析完毕以后,就会开始构建呈现树和设置布局。在不断接收和处理来自网络的其他内容的同时,呈现引擎会将部份内容解析并显示出来。

上面说到: 浏览器是一个边解析边渲染的过程。这个过程就涉及到两个比较重要的概念:重绘(repain)和回流(reflow)。

当页面中元素样式的改变并不影响它在文档流中的位置时(例如:colorbackground-colorvisibility等),浏览器会将新样式赋予给元素并从新绘制它,这个过程称为重绘。

Render Tree中部分或所有元素的尺寸、结构、或某些属性发生改变时,浏览器从新渲染部分或所有文档的过程称为回流。

会致使回流的操做

  • 页面首次渲染
  • 浏览器窗口大小发生改变
  • 元素尺寸或位置发生改变
  • 元素内容变化(文字数量或图片大小等等)
  • 元素字体大小变化
  • 添加或者删除可见的 DOM 元素
  • 激活 CSS 伪类(例如::hover)
  • 查询某些属性或调用某些方法

会致使回流的属性和方法

  • clientWidthclientHeightclientTopclientLeft
  • offsetWidthoffsetHeightoffsetTopoffsetLeft
  • scrollWidthscrollHeightscrollTopscrollLeft
  • scrollIntoView()scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

页面在首次加载的时候一定会经历reflowrepainreflowrepain 过程是很是消耗性能的,尤为是在移动设备上,它会破坏用户体验,有时会形成页面卡顿。因此咱们应该尽量少的减小 reflowrepain

链接结束(四次挥手)

TCP 的链接的拆除须要发送四个包,所以称为四次挥手(Four-way handshake),也叫作改进的三次握手。客户端或服务器都可主动发起挥手动做,在 socket 编程中,任何一方执行 close() 操做便可产生挥手操做。

  1. 第一次挥手(FIN=1,seq=x)

假设客户端想要关闭链接,客户端发送一个 FIN 标志位置为 1 的包,表示本身已经没有数据能够发送了,可是仍然能够接受数据。

发送完毕后,客户端进入 FIN_WAIT_1 状态。

  1. 第二次挥手(ACK=1,ACKnum=x+1)

服务器端确认客户端的 FIN 包,发送一个确认包,代表本身接受到了客户端关闭链接的请求,但尚未准备好关闭链接。

发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包以后,进入 FIN_WAIT_2 状态,等待服务器端关闭链接。

  1. 第三次挥手(FIN=1,seq=y)

服务器端准备好关闭链接时,向客户端发送结束链接请求,FIN 置为 1。

发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个 ACK。

  1. 第四次挥手(ACK=1,ACKnum=y+1)

客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT 状态,等待可能出现的要求重传的 ACK 包。

服务器端接收到这个确认包以后,关闭链接,进入 CLOSED 状态。

客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)以后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭链接,因而本身也关闭链接,进入 CLOSED 状态。

image

【问题 1】为何链接的时候是三次握手,关闭的时候倒是四次握手? 答:由于当 Server 端收到 Client 端的 SYN 链接请求报文后,能够直接发送 SYN+ACK 报文。其中 ACK 报文是用来应答的,SYN 报文是用来同步的。可是关闭链接时,当 Server 端收到 FIN 报文时,极可能并不会当即关闭 SOCKET,因此只能先回复一个 ACK 报文,告诉 Client 端,"你发的 FIN 报文我收到了"。只有等到我 Server 端全部的报文都发送完了,我才能发送 FIN 报文,所以不能一块儿发送。故须要四步握手。

【问题 2】为何 TIME_WAIT 状态须要通过 2MSL(最大报文段生存时间)才能返回到 CLOSE 状态?

答:虽然按道理,四个报文都发送完毕,咱们能够直接进入 CLOSE 状态了,可是咱们必须假象网络是不可靠的,有能够最后一个 ACK 丢失。因此 TIME_WAIT 状态就是用来重发可能丢失的 ACK 报文。

参考资料

相关文章
相关标签/搜索