Lasy

前端开发攻城狮~

从输入网址到网页显示出来发生了什么

从输入网址到网页显示出来发生了什么

关于这个问题,网上的答案已经很多了,但是每个人的答案侧重点都不同。 而我想尽可能详细地了解这个问题的答案,故写了此文。

概览

首先,这个过程包括以下部分:

  • DNS解析
  • 构建数据包
  • 三次握手
  • 发送请求
  • 服务器处理请求
  • 响应
  • 四次挥手
  • 解析数据
  • 渲染网页

一、DNS解析

概念

域名系统(英文:Domain Name System,缩写:DNS)是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。DNS使用TCP和UDP端口53。

过程

在输入网址后(假设网址为 www.google.com ),我们必须要得知它的IP地址才可以发送数据包。 这个时候,浏览器查询浏览器自身 DNS 缓存,如果存在记录则直接返回结果,如果记录过期或者不存在,则

  1. 查询系统中的 DNS 缓存,如果存在记录则直接返回结果,如果记录过期或者不存在,则
  2. 查询系统中的 Host 文件,如果存在记录则直接返回结果,如果记录不存在,则
  3. 发送查询报文”query www.google.com“到Local DNS(本地域名服务器,一般为当地运营商提供),Local DNS 查询自身 DNS 缓存,如果存在记录则直接返回结果(成功率较高),如果记录过期或者不存在,则
  4. Local DNS 向根域名服务器发送查询报文,根域名服务器返回 .com 域的权威域名服务器地址,这一级首先会返回的是顶级域名的权威域名服务器。
  5. Local DNS 向.com 域的权威域名服务器发送查询报文,得到 .google.com 域的权威域名服务器地址。
  6. Local DNS 向 .google.com 域的权威域名服务器发送查询报文,得到主机 www 的A记录(这条记录就是我们要的 IP 地址),存入自身缓存并返回给客户端(浏览器)。

经过DNS查询后,浏览器获得了 www.google.com 的 IP 地址。

扩展

  • 早期的域名必须以英文句号“.”结尾,当用户访问 www.google.com 的HTTP服务时必须在地址栏中输入:http://www.google.com.,这样DNS才能够进行域名解析。如今DNS服务器已经可以自动补上结尾的句号。
  • 记录类型:
    • 主机记录(A记录):RFC 1035定义,A记录是用于名称解析的重要记录,它将特定的主机名映射到对应主机的IP地址上。
    • 别名记录(CNAME记录): RFC 1035定义,CNAME记录用于将某个别名指向到某个A记录上,这样就不需要再为某个新名字另外创建一条新的A记录。
    • IPv6主机记录(AAAA记录): RFC 3596定义,与A记录对应,用于将特定的主机名映射到一个主机的IPv6地址。
    • 服务位置记录(SRV记录): RFC 2782定义,用于定义提供特定服务的服务器的位置,如主机(hostname),端口(port number)等。
    • NAPTR记录:RFC 3403定义,它提供了正则表达式方式去映射一个域名。NAPTR记录非常著名的一个应用是用于ENUM查询。

二、构造数据包

构造数据包要经过以下步骤:

1. 构造 HTTP 数据包

浏览网页用的是 HTTP(S) 协议,HTTP是应用层协议,应用层规定数据格式。 要在数据包中添加请求头,类似如下:

HTTP:

HTTPS:

2. 构造 TCP 数据包

TCP协议是传输层协议,传输层建立端口到端口的通信,Google 的HTTPS端口为 1081,浏览器发送请求的端口假设为 45252,所以 TCP 标头中将包含这两个端口信息,然后将标头与HTTP数据包连接构成 TCP 数据包。

3. 构造 IP 数据包

IP协议是网络层协议,网络层建立不同 IP 的设备之间的通信,IP 数据包中应该包含发送者和接收者的 IP。所以 IP 标头中将包含发送者 IP (假设为192.168.1.103)与接收者 IP (假设为174.37.154.236),然后将标头与 TCP 数据包连接构成 IP 数据包。

4. 构造以太网数据包

以太网协议是链接层协议,链接层在实体层的上方,确定了0和1的分组方式。以太网协议的标头中包含了一些说明项,比如发送者 MAC地址、接收者MAC地址、数据类型等等。然后将以太网标头与 IP 数据包连接构成以太网数据包。 这里要获得接收者的MAC地址需要用到 ARP 技术。

地址解析协议 (ARP) 是通过解析网路层地址来找寻数据链路层地址的一个在网络协议包中极其重要的网络传输协议。

对于在同一局域网内的设备可以通过ARP直接获得MAC地址,若不在同一局域网内则会返回网关的MAC地址。因此,这里的接收者MAC地址为网关的MAC地址。

判断是否在同一局域网的方法:

这里要用到的是 子网掩码。这里我们的子网掩码是 255.255.255.0,将其与本机IP( 192.168.1.103)进行与运算,得到结果 192.168.1.0;将子网掩码与 Google 的 IP(174.37.154.236) 进行与运算得到 174.37.154.0,将这两个结果进行比较,并不想等,所以不在同一个局域网内。

至此,浏览器已经将要发送的数据包构建好。

三、三次握手

待补充……

四、发送请求

NAT

我们的设备存在于内网中,众所周知,内网的IP地址是不可能被外网拿到的,内网的 IP 地址是 C类IP地址,C类IP地址并不唯一,不能作为发送者的一种身份,但是IP地址又是我们确定对方身份的第一步,那么怎么做呢?这里就需要 NAT

网络地址转换(Network Address Translation,缩写为 NAT),也叫做网络掩蔽或者IP掩蔽(IP masquerading),是一种在IP数据包通过路由器或防火墙时重写来源IP地址或目的IP地址的技术。

浏览器构造的以太网数据包在经过具有NAT功能的网关(一般是路由器)时,网关通过子网掩码判断接收者 IP 是否存在于该局域网中,如果存在,则将该数据包发送给该IP地址的设备,如果不存在,则对数据包进行解包,并做以下替换:

  1. 将发送者IP替换为网关IP;
  2. 发送者端口替换为网关提供的一个端口;
  3. 发送者MAC替换为网关MAC地址;
  4. 接收者MAC替换为上一级网关的MAC地址。

然后对数据包进行封包,并发送给上一层网关,这一过程就是NAT。 上一层网关接收到数据包后,判断局域网中是否有该IP,如果存在,则将该数据包发送到该IP地址(即接收者)的接收端口上,如果不存在,则将接收者MAC替换为上一级网关后,继续将数据包发送给上一级网关, 之后递归执行此步骤,直到找到接收者IP存在于同一局域网,这时候将数据包发送给接收者IP的接收端口。至此,服务器收到了浏览器的请求数据。 扩展: 这时的数据包中:

  1. 发送者IP:如果客户端存在于具有NAT功能的网关下,则为具有NAT功能的网关IP;否则为客户端IP。
  2. 发送者MAC:如果客户端存在于具有NAT功能的网关下,则为具有NAT功能的网关MAC;否则为客户端MAC。
  3. 接收者IP为服务器IP;
  4. 接收者MAC为服务器所在网关MAC;

五、服务器处理

服务器端会有web服务器监听端口,如本例中的1081。当请求发送到1081端口时,web服务器接收请求并进行解析,然后发送响应。

常见的Web服务器

  • Apache
  • Nginx
  • IIS
  • Tomcat
  • nodejs

六、响应

HTTP响应报文主要由状态行、响应头部、空行以及响应数据组成。例如

响应的发送与请求的发送是一个相反的过程,数据包沿着发送的路径原路返回,最后到达客户端(浏览器)。

七、四次挥手

待补充……

八、解析数据

浏览器接收到响应的数据包之后,解包拿到HTTP响应报文。再从HTTP响应报文中取出响应数据,即HTML代码。

九、渲染网页

浏览器获得HTML之后,便开始解析渲染。

  1. 构建DOM Tree;
  2. 构建CSSOM Tree;
  3. 构建Render Tree渲染树;
  4. Layout布局;
  5. 绘制。

1. 构建DOM Tree

DOM是文档对象化模型(Document Object Model)的简称。DOM Tree是指通过DOM将HTML页面进行解析,并生成的HTML tree树状结构和对应访问方法。

HTML Parser将HTML标记解析为DOM Tree。

例如,这样的HTML:

最后DOM Tree就会是如下形式:

《从输入网址到网页显示出来发生了什么》 (示例与图片来源于Google Developers

2. 构建CSSOM Tree

CSS Parser将CSS解析为DOM Tree。

对于以下CSS:

会形成如下所示CSSOM Tree:

《从输入网址到网页显示出来发生了什么》 (示例与图片来源于Google Developers

这里的CSSOM Tree并不完全,实际的CSSOM Tree中还应该包含浏览器的默认样式。

3. 构建Render Tree渲染树

浏览器将DOM和CSSOM合并成一个“渲染树”,这个渲染树包含了网页上所有可见的DOM内容,以及每个节点的所有CSSOM样式信息。也就是说,不可见的节点不会出现在渲染树中。 注:不可见是指的是:

  • 本身不可见的:<html><head><meta><link><style><script>
  • 设置了display:none的。

合并之后的Render Tree:

《从输入网址到网页显示出来发生了什么》 (图片来源于Google Developers

4. Layout布局

布局阶段的任务是确定节点的位置和大小,这个阶段浏览器会将节点的位置和大小转换为屏幕上的绝对像素。

5. 绘制

这一步,浏览器已经拥有了要绘制所需的所有信息,只需要将节点绘制到浏览器中即可。

注意事项:

  • HTML和CSS的下载解析是并行的。也就是说DOM Tree和CSSOM Tree同时构建。
  • 在构建DOM Tree的时候一旦遇到 link标签中外链式的CSS,就会立即发出对该资源的请求,该过程是异步的,不会阻塞渲染。
  • HTML和CSS都是阻塞渲染的资源。如果DOM Tree或者CSSOM Tree没有构建完,就无法构建渲染树。这个时候会阻塞渲染。直到构建完成,才能继续渲染。
  • JavaScript脚本是立即执行的。因此,遇到 script 标签,浏览器会阻塞渲染,直到执行完JavaScript脚本。但是有一个特例:见下一条
  • 当遇到 script 标签时,如果CSSOM Tree还没有构建完成,浏览器将延迟脚本执行和DOM Tree构建,直至其完成CSS的下载和CSSOM的构建。简单来说,script 标签中代码执行的前提是构建好CSSOM Tree,如果没有,那就延迟脚本执行和DOM Tree构建。其实这是一个竞态问题(设备或系统出现不恰当的执行时序,而得到不正确的结果),浏览器的解决方案就是延迟执行。

结语

以上就是从输入网址到网页显示整个过程发生的事情,我尽可能详细地列了出来,但是对于每一部分其实都是可以写一篇文章的,我并没有很细致地展开讨论。

在这里,我总结了一下整篇文章中涉及到的知识点:

  • DNS
  • 互联网协议
  • ARP
  • NAT
  • Web server
  • 浏览器是如何工作的

参考链接:

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注