回炉计划第三篇,这是一个经典的前端面试题,考察范围很是的广,可深刻的角度也很是的多。本篇文章的目的主要是回顾,因此内容和网络上流传的文章会有必定的重叠性。css
过程大体分为如下几个步骤html
DNS 服务和 HTTP 协议同样,都是位于应用层的协议,它提供域名到 ip 地址之间的解析服务。 以查询www.baidu.com
的 ip 地址为例前端
补充:域名和 url 是两个概念,域名是用来确认服务器的地址的,而 url 是用来确认资源的地址;域名和 ip 地址不是一一对应的,一个域名同一时刻只能解析出一个 ip 地址,而一个 ip 地址能够绑定多个域名html5
这就涉及到著名的 http 三次握手。简单来讲与服务器创建链接须要经历如下三个过程。web
syn
包(syn=j
)到服务器,并进入 SYN_SEND 状态,等待服务器确认;syn
包,必须确认客户的 syn
(ack=j+1
),同时本身也发送一个 SYN
包(syn=k
),即 SYN+ACK
包,此时服务器进入 SYN_RECV
状态;SYN+ACK
包,向服务器发送确认包 ACK
(ack=k+1
),此包发送完毕,客户端和服务器进入 ESTABLISHED
状态,完成三次握手。这里能够延申拓展一下 HTTPS 的知识 HTTPS 详解--segmentfault面试
这一步主要是后端从接口获取到 tcp 报文,处理以后返回HTTP Request
对象,也就是响应报文。编程
HTTP 响应报文也是由三部分组成: 状态码, 响应报头和响应报文。segmentfault
状态码由三位数字组成,表示响应的类型。状态码有五大类 1xx,2xx,3xx,4xx,5xx后端
响应报头 HTTP 请求头提供了关于请求,响应或者其余的发送实体的信息。 HTTP 响应头信息-菜鸟编程
响应报文:就是服务器返回给浏览器的文本信息了,包括 html,js,css 等资源
浏览器拿到响应报文以后,开始解析报文并呈现网页。因为不一样的浏览器引擎实现的方法可能不一致,咱们以webkit
内核为例进行说明。 WebKit 渲染的过程大体分为四步 浏览器的工做原理:新式网络浏览器幕后揭秘
构建 dom 树 -> 构建 render 树 -> 布局 render 树 -> 绘制 render 树
呈现引擎将开始解析 HTML 文档,并将各标记逐个转化成“内容树”上的 DOM 节点。同时也会解析外部 CSS 文件以及样式元素中的样式数据。HTML 中这些带有视觉指令的样式信息将用于建立另外一个树结构:呈现树。
呈现树包含多个带有视觉属性(如颜色和尺寸)的矩形。这些矩形的排列顺序就是它们将在屏幕上显示的顺序。
呈现树构建完毕以后,进入“布局”处理阶段,也就是为每一个节点分配一个应出如今屏幕上的确切坐标。下一个阶段是绘制 - 呈现引擎会遍历呈现树,由用户界面后端层将每一个节点绘制出来。
须要着重指出的是,这是一个渐进的过程。为达到更好的用户体验,呈现引擎会力求尽快将内容显示在屏幕上。它没必要等到整个 HTML 文档解析完毕以后,就会开始构建呈现树和设置布局。在不断接收和处理来自网络的其他内容的同时,呈现引擎会将部份内容解析并显示出来。
上面说到: 浏览器是一个边解析边渲染的过程。这个过程就涉及到两个比较重要的概念:重绘(repain)和回流(reflow)。
当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color
、background-color
、visibility
等),浏览器会将新样式赋予给元素并从新绘制它,这个过程称为重绘。
当Render Tree
中部分或所有元素的尺寸、结构、或某些属性发生改变时,浏览器从新渲染部分或所有文档的过程称为回流。
会致使回流的操做
会致使回流的属性和方法
clientWidth
、clientHeight
、clientTop
、clientLeft
offsetWidth
、offsetHeight
、offsetTop
、offsetLeft
scrollWidth
、scrollHeight
、scrollTop
、scrollLeft
scrollIntoView()
、scrollIntoViewIfNeeded()
getComputedStyle()
getBoundingClientRect()
scrollTo()
页面在首次加载的时候一定会经历reflow
和repain
。reflow
和 repain
过程是很是消耗性能的,尤为是在移动设备上,它会破坏用户体验,有时会形成页面卡顿。因此咱们应该尽量少的减小 reflow
和 repain
。
TCP 的链接的拆除须要发送四个包,所以称为四次挥手(Four-way handshake),也叫作改进的三次握手。客户端或服务器都可主动发起挥手动做,在 socket 编程中,任何一方执行 close() 操做便可产生挥手操做。
假设客户端想要关闭链接,客户端发送一个 FIN 标志位置为 1 的包,表示本身已经没有数据能够发送了,可是仍然能够接受数据。
发送完毕后,客户端进入 FIN_WAIT_1 状态。
服务器端确认客户端的 FIN 包,发送一个确认包,代表本身接受到了客户端关闭链接的请求,但尚未准备好关闭链接。
发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包以后,进入 FIN_WAIT_2 状态,等待服务器端关闭链接。
服务器端准备好关闭链接时,向客户端发送结束链接请求,FIN 置为 1。
发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个 ACK。
客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT 状态,等待可能出现的要求重传的 ACK 包。
服务器端接收到这个确认包以后,关闭链接,进入 CLOSED 状态。
客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)以后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭链接,因而本身也关闭链接,进入 CLOSED 状态。
【问题 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 报文。