浏览器从输入URL到页面加载完成经历了什么

1,160 阅读5分钟

本文正在参与 “网络协议必知必会”征文活动

前端角度

常见的URL是这样的www.baidu.com, 其实域名有三部分组成:协议名、域名、端口号,一般来说端口是默认隐藏的,除此之外还会包含一些路径、查询和其他字段;

那么从输入url到页面加载完成发生了什么呢?我的简单理解可以大致总结来说这几点:

  1. 地址栏输入url并按下回车键;
  2. 浏览器查找当前url的DNS缓存记录,并比较缓存是否过期;
  3. DNS解析url的的对应IP;
  4. 根据IP建立TCP连接(三次握手);
  5. HTTP发起请求;
  6. 服务器处理请求,浏览器接收HTTP响应;
  7. 页面渲染,构建DOM树;
  8. 关闭TCP连接;(四次握手)

其中有几个关键过程:DNS解析、TCP建立连接+HTTP请求、接收响应、浏览器渲染页面、断开连接。下面是对这几个关键过程的一些简单解释:

DNS域名解析

域名解析的过程实际就是将域名还原为IP地址的过程,因为我们知道地址栏输入的域名并不是最后资源真实所在位置,域名只是 IP地址的一个映射。

浏览器首先检查本地hosts文件是否有这个网址映射关系,如果有就调用这个IP地址的映射,完成域名解析。

如果没有找到则会查找本地DNS解析器缓存,如果查找到则返回。

如果还是没有找到则会查找本地DNS服务器,如果查找到则返回。

最后递归查询,按照本地域名服务器根域名服务器顶级域名服务器权威域名服务器对应网址的解析过程就是:.->.com ->baidu.com.->www.baidu.com

TCP连接+HTTP请求

通过第一步的DNS域名解析之后,获取到服务器的IP地址,开始建立一次连接,这是由TCP协议完成,主要通过三次握手进行连接;

首先通俗讲三次握手的过程:
客户端:你好,我要请求数据了;
服务器端:你好,可以的;
客户端:好的。

下面客观说一下三次握手

  • 第一次握手: 建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;
  • 第二次握手: 服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
  • 第三次握手: 客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

完成三次握手,客户端与服务器开始传输数据。

1034346-20170329145607592-1103856922.png

HTTP请求主要发生在客户端,这部分又可以称为前端工程师眼中的HTTP,发送HTTP请求的过程就是构建HTTP请求报文并通过TCP协议发到服务器指定端口(HTTP协议80/8080,HTTPS协议443)。报文由三部分组成:请求行,请求头,请求实体。

浏览器接收响应

服务器在收到浏览器发送的HTTP请求之后,会将收到的HTTP报文封装成HTTP的Request对象,并通过不同的Web服务器进行处理,处理完的结果以HTTP的Response对象返回,主要包括状态码,响应头,响应报文三个部分。

  状态码主要包括以下部分

  1xx:指示信息–表示请求已接收,继续处理。

  2xx:成功–表示请求已被成功接收、理解、接受。

  3xx:重定向–要完成请求必须进行更进一步的操作。

  4xx:客户端错误–请求有语法错误或请求无法实现。

  5xx:服务器端错误–服务器未能实现合法的请求。

  响应头主要由Cache-Control、 Connection、Date、Pragma等组成。

  响应体为服务器返回给浏览器的信息,主要由HTML,css,js,图片文件组成。

详情请参考另一篇 HTTP状态码文章

浏览器渲染页面

浏览器把页面呈现给用户,整个过程涉及两个方面:解析和渲染。

  1. 处理HTML标记并构建DOM树;
  2. 处理css标记并构建CSSOM树
  3. 将DOM树和CSSOM树合并构建一个渲染树;
  4. 渲染树布局,浏览器通过Render Tree计算出每个节点对象在页面的确切大小和位置;
  5. 渲染树绘制,浏览器会调用渲染器的paint()方法在屏幕上显示内容。 DOMContentLoaded事件触发代表初始的HTML被完全加载和解析,不需要等待CSS,JS,图片加载。

Load事件触发代表页面中的DOM,CSS,JS,图片已经全部加载完毕。

关闭TCP连接

通过四次挥手关闭连接(FIN ACK, ACK, FIN ACK, ACK)。

1034346-20170329153945389-2019926409.png

 通俗讲:
    客户端:我要断开连接了;
    服务器端:收到;
    服务器:我也要断开连接了;
    客户端:收到(我会在2倍的报文最大生存时间后断开连接,如果在这个时间内再收到服务器的消息,我就再发送一遍确认信息)。
    

第一次挥手是浏览器发完数据后,发送FIN请求断开连接。

第二次挥手是服务器发送ACK表示同意,如果在这一次服务器也发送FIN请求断开连接似乎也没有不妥,但考虑到服务器可能还有数据要发送,所以服务器发送FIN应该放在第三次挥手中。

这样浏览器需要返回ACK表示同意,也就是第四次挥手。

至此从浏览器地址栏输入URL到页面呈现到你面前的整个过程就分析完了, 特别鸣谢: 踮起脚尖眺望3

欢迎留言交流指教💕💕💕