学习笔记:输入url到页面渲染的整个过程


原文:https://github.com/alex/what-happens-when

解析URL

浏览器通过URL知道协议与请求的资源,当协议或主机名不合法时,将地址栏中输入的文字传给默认的搜索引擎。并且浏览器检查输入是否有非ASCII的字符,如果有会使用Punycode编码。
浏览器检查自带的“预加载 HSTS(HTTP严格传输安全)”列表,这个列表里包含了那些请求浏览器只使用HTTPS进行连接的网站。如果网站在这个列表里,浏览器会使用 HTTPS 而不是 HTTP 协议,否则,最初的请求会使用HTTP协议发送。

DNS

DNS 的作用就是通过域名查询到具体的 IP。

DNS查询

  1. 浏览器检查域名是否在缓存当中(要查看 Chrome 当中的缓存, 打开 chrome://net-internals/#dns)。
  2. 如果缓存中没有,就去调用 gethostbyname 库函数(操作系统不同函数也不同)进行查询。
  3. gethostbyname 函数在试图进行DNS解析之前首先检查域名是否在本地 Hosts 里,Hosts 的位置不同的操作系统有所不同
  4. 如果 gethostbyname 没有这个域名的缓存记录,也没有在 hosts 里找到,它将会向 DNS 服务器发送一条 DNS查询请求。DNS 服务器是由网络通信栈提供的,通常是本地路由器或者 ISP 的缓存 DNS 服务器。
  5. 查询本地 DNS 服务器
  6. 如果 DNS 服务器和我们的主机在同一个子网内,系统会按照下面的 ARP 过程对 DNS 服务器进行 ARP查询
  7. 如果 DNS 服务器和我们的主机在不同的子网,系统会按照下面的 ARP 过程对默认网关进行查询

ARP 过程

我们通过目标 IP 地址,和用于发送 ARP 广播的接口的 MAC 地址来发送 ARP(地址解析协议)广播。得到一个 ARP Reply,获得了DNS 服务器或者默认网关的 IP 地址,继续 DNS 请求:

  1. 使用 53 端口向 DNS 服务器发送 UDP 请求包,如果响应包太大,会使用 TCP 协议
  2. 如果本地/ISP DNS 服务器没有找到结果,它会发送一个递归查询请求,一层一层向高层 DNS服务器做查询,直到查询到起始授权机构,如果找到会把结果返回。
  3. DNS迭代查询与递归查询的区别就是前者是由客户端去做请求,后者是由系统配置的 DNS 服务器做请求,得到结果后将数据返回给客户端。

TCP

使用套接字

当浏览器得到了目标服务器的 IP 地址,以及 URL 中给出来端口号(http 协议默认端口号是 80, https 默认端口号是 443),它会调用系统库函数 socket ,请求一个 TCP流套接字,对应的参数是 AF_INET/AF_INET6 和 SOCK_STREAM 。

  1. 这个请求首先被交给传输层,在传输层请求被封装成 TCP segment。目标端口会被加入头部,源端口会在系统内核的动态端口范围内选取(Linux下是ip_local_port_range)
  2. TCP segment 被送往网络层,网络层会在其中再加入一个 IP头部,里面包含了目标服务器的IP地址以及本机的IP地址,把它封装成一个IP packet。
  3. 这个 TCP packet 接下来会进入链路层,链路层会在封包中加入 frame头部,里面包含了本地内置网卡的MAC地址以及网关(本地路由器)的 MAC 地址。像前面说的一样,如果内核不知道网关的 MAC地址,它必须进行 ARP 广播来查询其地址。

TCP传输

建立连接时

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

关闭连接时

  1. TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
  2. 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
  3. 服务器关闭客户端的连接,发送一个FIN给客户端。
  4. 客户端发回ACK报文确认,并将确认序号设置为收到序号加1。

TLS握手

  • 客户端发送一个 ClientHello 消息到服务器端,消息中同时包含了它的 Transport LayerSecurity(TLS)版本,可用的加密算法和压缩算法。
  • 服务器端向客户端返回一个 ServerHello消息,消息中包含了服务器端的TLS版本,服务器所选择的加密和压缩算法,以及数字证书认证机构(CertificateAuthority,缩写CA)签发的服务器公开证书,证书中包含了公钥。客户端会使用这个公钥加密接下来的握手过程,直到协商生成一个新的对称密钥
  • 客户端根据自己的信任CA列表,验证服务器端的证书是否可信。如果认为可信,客户端会生成一串伪随机数,使用服务器的公钥加密它。这串随机数会被用于生成新的对称密钥
  • 服务器端使用自己的私钥解密上面提到的随机数,然后使用这串随机数生成自己的对称主密钥
  • 客户端发送一个 Finished 消息给服务器端,使用对称密钥加密这次通讯的一个散列值 服务器端生成自己的 hash值,然后解密客户端发送来的信息,检查这两个值是否对应。如果对应,就向客户端发送一个 Finished 消息,也使用协商好的对称密钥加密
  • 从现在开始,接下来整个 TLS 会话都使用对称秘钥进行加密,传输应用层(HTTP)内容

HTTP 协议

HTTP 协议

HTTP 服务器请求处理

HTTPD(HTTP Daemon)在服务器端处理请求/响应。最常见的 HTTPD 有 Linux 上常用的 Apache 和 nginx,以及 Windows 上的 IIS。

  1. HTTPD 接收请求
  2. 服务器把请求拆分为以下几个参数:
    HTTP 请求方法(GET, POST, HEAD, PUT, DELETE, CONNECT, OPTIONS, 或者TRACE)。直接在地址栏中输入 URL 这种情况下,使用的是 GET 方法
    域名:google.com
    请求路径/页面:/ (我们没有请求google.com下的指定的页面,因此 / 是默认的路径)
  3. 服务器验证其上已经配置了 google.com 的虚拟主机
  4. 服务器验证 google.com 接受 GET 方法
  5. 服务器验证该用户可以使用 GET 方法(根据 IP 地址,身份信息等)
  6. 如果服务器安装了 URL 重写模块(例如 Apache 的 mod_rewrite 和 IIS 的 URLRewrite),服务器会尝试匹配重写规则,如果匹配上的话,服务器会按照规则重写这个请求
  7. 服务器根据请求信息获取相应的响应内容,这种情况下由于访问路径是 “/” ,会访问首页文件(你可以重写这个规则,但是这个是最常用的)。
  8. 服务器会使用指定的处理程序分析处理这个文件,假如 Google 使用 PHP,服务器会使用 PHP 解析 index文件,并捕获输出,把 PHP 的输出结果返回给请求者

浏览器

浏览器的功能是从服务器上取回你想要的资源,然后展示在浏览器窗口当中。资源通常是 HTML 文件,也可能是 PDF,图片,或者其他类型的内容。资源的位置通过用户提供的 URI(Uniform Resource Identifier) 来确定。

浏览器高层架构

组成浏览器的组件有:

  • 用户界面 用户界面包含了地址栏,前进后退按钮,书签菜单等等,除了请求页面之外所有你看到的内容都是用户界面的一部分
  • 浏览器引擎 浏览器引擎负责让 UI 和渲染引擎协调工作
  • 渲染引擎 渲染引擎负责展示请求内容。如果请求的内容是 HTML,渲染引擎会解析 HTML 和 CSS,然后将内容展示在屏幕上
  • 网络组件 网络组件负责网络调用,例如 HTTP 请求等,使用一个平台无关接口,下层是针对不同平台的具体实现
  • UI后端 UI 后端用于绘制基本 UI 组件,例如下拉列表框和窗口。UI 后端暴露一个统一的平台无关的接口,下层使用操作系统的 UI方法实现
  • Javascript 引擎 Javascript 引擎用于解析和执行 Javascript 代码
  • 数据存储 数据存储组件是一个持久层。浏览器可能需要在本地存储各种各样的数据,例如 Cookie 等。浏览器也需要支持诸如localStorage,IndexedDB,WebSQL 和 FileSystem 之类的存储机制

渲染

HTML 解析

浏览器渲染引擎从网络层取得请求的文档,一般情况下文档会分成8kB大小的分块传输。

HTML 解析器的主要工作是对 HTML 文档进行解析,生成解析树。

解析树是以 DOM 元素以及属性为节点的树。DOM是文档对象模型(Document Object Model)的缩写,它是 HTML 文档的对象表示,同时也是 HTML 元素面向外部(如Javascript)的接口。树的根部是"Document"对象。整个 DOM 和 HTML 文档几乎是一对一的关系。

构建方式:首先,将Response body中的html字符流代码通过状态机进行词法分析拆分成词(token),接下来词会转换为节点(node),不同的节点通过联系构建成dom树

CSS 解析

  • 根据 CSS词法和句法 分析CSS文件和style标签包含的内容以及style 属性的值
  • 每个CSS文件都被解析成一个样式表对象(StyleSheetobject),这个对象里包含了带有选择器的CSS规则,和对应CSS语法的对象
  • CSS解析器可能是自顶向下的,也可能是使用解析器生成器生成的自底向上的解析器

页面渲染

  1. 通过遍历DOM节点树创建一个“Frame 树”或“渲染树”,并计算每个节点的各个CSS样式值
  2. 通过累加子节点的宽度,该节点的水平内边距(padding)、边框(border)和外边距(margin),自底向上的计算"Frame
    树"中每个节点的首选(preferred)宽度
  3. 通过自顶向下的给每个节点的子节点分配可行宽度,计算每个节点的实际宽度
  4. 通过应用文字折行、累加子节点的高度和此节点的内边距(padding)、边框(border)和外边距(margin),自底向上的计算每个节点的高度
  5. 使用上面的计算结果构建每个节点的坐标
  6. 当存在元素使用 floated,位置有 absolutely 或 relatively属性的时候,会有更多复杂的计算,详见http://dev.w3.org/csswg/css2/ 和http://www.w3.org/Style/CSS/current-work
  7. 创建layer(层)来表示页面中的哪些部分可以成组的被绘制,而不用被重新栅格化处理。每个帧对象都被分配给一个层
    页面上的每个层都被分配了图形
  8. 每个层的帧对象都会被遍历,计算机执行绘图命令绘制各个层,此过程可能由CPU执行栅格化处理,或者直接通过D2D/SkiaGL在GPU上绘制
  9. 上面所有步骤都可能利用到最近一次页面渲染时计算出来的各个值,这样可以减少不少计算量
  10. 计算出各个层的最终位置,一组命令由 Direct3D/OpenGL发出,GPU命令缓冲区清空,命令传至GPU并异步渲染,帧被送到Window Server。

GPU渲染

  1. 在渲染过程中,图形处理层可能使用通用用途的 CPU,也可能使用图形处理器 GPU
  2. 当使用 GPU 用于图形渲染时,图形驱动软件会把任务分成多个部分,这样可以充分利用 GPU强大的并行计算能力,用于在渲染过程中进行大量的浮点计算。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值