浏览器输入地址之后发生了什么

419 阅读6分钟

主要几个过程:

1. DNS域名解析

2. 建立起TCP连接,三次握手

3. 发起HTTP请求

4. 服务器响应请求,浏览器获取到内容

5. 解析页面流程

6. 回流与重绘

7. JS引擎解析

8. 断开连接,四次挥手

一、 DNS域名解析

  1. 浏览器首先检查缓存中有没有这个域名对应解析过的IP地址,如果有,解析就会结束。(缓存时间不长,大概一分钟,容纳1000条缓存)
  2. 检查操作系统缓存中是否有这个域名对响应的DNS解析结果
  3. 读取本地的一个hosts文件,查找域名对应解析过的IP地址
  4. 如果依旧没有找到,就会向本地服务器查询(LDNS),比如你是小区上网,那么这个本地服务器一般都是网络提供商,比如电信的DNS服务器
  5. 接下来就是根域名服务器解析。返回给本地服务器一个所查询的主域名服务器,比如是.com .cn .org
  6. 本地服务器再向上一步返回来的主域名服务器发送请求
  7. 接收请求的顶级域名服务器返回这个域名对应的一个权威服务器(Name Server),就是你注册的一个域名服务器,例如用户在某个域名服务提供商申请的域名
  8. 权威服务器查询存储的域名和IP的映射关系表,然后将IP连同一个TTL值返回给域名服务器
  9. 本地服务器拿到这个IP和TTL缓存起来,缓存时间是TTL控制
  10. 最后返回解析结果给用户。用户根据TTL值缓存在本地系统中,域名解析结束

浏览器缓存 --> 操作系统缓存 --> hosts文件 --> 根域名服务器

二、建立TCP连接,三次握手

  1. 客户端首先发送一个连接试探(ACK=0表示确认号无效,SYN=1表示是一个连接请求或者接受报文,seq=x表示客户端初始序号包)
  2. 服务端监听到请求报文后,同意建立连接,向客户端发送请求
  3. 客户端收到确认后还需要再次发送确认,并且携带要发送给服务器的数据

三次握手是为了防止出现失效的连接请求报文被服务端接收的情况。第一次握手是不会携带数据的

比如:客户端发送一个连接请求A,但突然因为网络原因造成超时,TCP就会启动超时重传机制再次发送一个连接请求B,请求顺利到达了服务端。服务端接收数据之后释放连接。但是假如这个时候连接请求A在两端关闭后抵达了服务器,服务器就会答应请求,一直等待,造成资源的浪费

而为什么不能两次握手,是因为这样服务端只是怼客户端做了确认,客户端并没有做确认,并不能保证传输。而四五次以上就会造成一个资源的浪费

通俗化就是:

客户端:老哥,在吗,有你的信

服务端:在的,送过来就行

客户端:好的

三、发起HTTP请求

与服务器建立连接后,就可以发起请求。请求报文中包括请求行、请求头、空行、请求主体。http默认端口是80,https是443

http和https区别

  1. https协议需要ca申请证书,免费证书较少,需要一定费用
  2. http是明文传输,https是具有安全性的ssl加密传输协议
  3. http和https使用不同的连接方式,端口也不同

四、服务器响应请求

HTTP响应由三个部分组成,分别:状态行、消息报头、响应体

  • 1xx:信息性(接收的请求正在处理)
  • 2xx:成功请求
  • 3xx:重定向(需要进一步操作完成请求)
  • 4xx:客户端错误
  • 5xx:服务端错误

五、解析页面流程

  • html解析,构建DOM树

    Bytes --> characters --> tokens --> nodes --> DOM 1. 浏览器将获得的Bytes基于编码转换成html代码(解码) 2. 浏览器根据html规范将字符转换不同的token 3. 将一堆token转换成对象,对象分别定义属性和规则 4. DOM构建

  • CSS解析,构建CSS规则树

CSS解析,选择器是从右向左解析
如果从左到右匹配,发现不符合规则的时候会回溯,损失性能。而从右向左匹配,从第一步就筛选掉大量不符合的子节点。
  • 合并DOM树和CSS规则树,生成render树

  • 布局render树,负责各个元素的尺寸,位置计算

  • 绘制render树,绘制页面像素信息

  • 浏览器将各层的信息发送给GPU,GPU将各层合并显示在屏幕上

    HTML --> HTML Parser --> DOM Tree
    Style Sheets --> CSS Parser --> Style Tree
    DOM Tree + Style Tree --> Render Tree
    Layout(Render Tree) --> Painting --> Display
    

六、重绘与回流

重绘:元素发生的改变只是影响元素的一些外观

回流:元素的内容、结构、位置、尺寸发生改变,需要重新计算样式,回流是一定伴随重绘,但是重绘是单独出现的

以下行为都会触发到回流:

  • 页面渲染初始化
  • DOM结构变化,比如增加删除节点
  • render树变化,比如增加减少padding
  • 窗口的resize
  • 获取一些属性(offset,scroll,client,width,height,getComputedStyle())
  • 改变字体的大小

优化回流:

  • 减少逐项去修改样式

  • 避免循环操作DOM

  • 谨慎使用table布局,因为一个小改动就会造成整个table的重新布局

  • 使用visibility代替display:none,前者只会引起重绘,后者会引发回流

    var s = document.body.styles.padding = "10px" // 回流+重绘 s.border = "1px solid red" // 回流+重绘 s.color = 'red' // 重绘 s.backgroundColor = "blue" // 重绘 s.fontSize ="20px" // 回流+重绘 document.body.appendChild(document.createTextNode('a')) // 添加node,回流+重绘

七、JS引擎解析

  • 浏览器首次加载脚本,创建全局上下文,并压入栈顶
  • 每进入其他作用域就创建对应的执行上下文并把它压入执行栈
  • 一旦对应的上下文执行完成,就从栈顶弹出

八、断开连接,四次挥手

  1. 客户端发送断开连接请求
  2. 服务端接收请求,发回一个确认
  3. 服务端向客户端发送结束,服务端关闭客户端的连接
  4. 客户端向服务端发送确认,服务端收到后关闭,客户端等待一段时间也进行关闭状态

四次挥手是为了:服务端收到客户端的关闭连接请求,不会立即关闭连接。需要等待所有数据传输完毕后才关闭。所以先回复客户收到了报文,数据传输完毕才告诉客户端可以进行关闭。客户端回复报文进行确认,这才算是真正的关闭了。

通俗化就是:

客户端:大哥,我们关闭连接叭

服务端:好,收到了

服务端:我这也没啥要传输的,关了哦

客户端:OK