天天看点

从URL输入到页面展示发生了什么

总的来说就是下面几个过程:

DNS解析:将域名解析成IP地址

TCP连接:TCP的三次握手

发送HTTP请求

服务器处理请求并返回HTTP报文

浏览器解析渲染页面

断开连接:TCP四次挥手

URL到底是啥

URL(Uniform Resource Locator)统一资源定位符,用于定位互联网上资源,俗称网络.遵循以下语法规则:

scheme://host.domain:port/path/filename

scheme:定义因特网服务的类型,常见的类型有:HTTP HTTPS和GTP。

host:定义域主机(http默认是www)

domain:定义因特网域名,比如xxx.com.cn

port:定义主机上的端口号(http:默认是80)

path:定义服务器上的路径

filename:定义文档/资源的名称

1 DNS解析

在浏览器输入网址后,首先要经过域名解析,因为浏览器并不能直接通过域名找到对应的服务器,而是要通过IP地址,之所以我们用的是域名而不是IP,是因为IP是一段数字,特别不容易记住,而域名其实就是IP的伪装者。

什么是域名解析

DNS协议提供通过域名查找IP地址,或者是反向通过IP查找域名的服务。DNS是一个网络服务器,我们的域名解析简单来说就是DNS上记录一条信息记录。

浏览器如何通过域名去查找URL对应的IP的

最厉害的飞机票

上面有飞机,这里就不详细解析。

小结

浏览器通过DNS服务器发送域名,DNS服务器查询与域名对应的IP地址,然后返回给浏览器,浏览器再将IP地址打在协议上,同时请求参数也会在协议搭载,然后一并发送给对方的服务器。接下来介绍向服务器发送HTTP请求阶段,HTTP请求分为三个部分:TCP三次握手,http请求信息,关闭TCP链接

2 TCP三次握手
从URL输入到页面展示发生了什么

1 三次握手的过程如下:

  • 客户端发送一个带有SYN=1和Seq=X的数据报到服务器断端口(第一次握手是由浏览器发起,告诉服务器我要发送请求了)
  • 服务器返回了一个带SYN=1 ACK=X+1,Seq=Y的响应报以示传达确认信息(第二次握手,由服务器发送,告诉浏览器我准备接受了,你赶紧发送)
  • 客户端再传一个带ACK=Y+1,Seq=Z的数据包,代表"握手结束"(第三次握手,有浏览器发送,告诉服务器,我马上就发了,准备接受吧)

为啥需要三次握手

主要是为了防止已失效的连接请求突然又传送到服务器上。

所谓"已失效的链接请求报文段"是这样产生的,考虑一种正常情况:客户端发出连接请求,但因连接请求报文丢失而未收到确认,于是客户端再重传一次链接请求,后来收到了确认,建立了连接。数据传输后,就释放了连接。客户端共发送了两个连接请求报文,其中一个丢失,另一个到达了服务器,这样是没有失效的连接请求。

但是如果出现一种异常情况,即客户端发出的第一个连接请求报文文段没有丢失,而是在某个网络节点长时间滞留(网差),以致延误到连接释放以后的某个时间才到达服务器,本来这是一个早就已失效的报文段,但服务器收到失效的连接请求报文后,就误以为客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接,假定不采用报文握手,那么只要服务器发出确认就建立连接,新的连接就建立了。

由于现在客户端并没有发出建立连接的请求,因此不会理会服务器的确认,也不会向服务器发送数据,但是服务器确认为新的运输连接已经建立,并一直等待客户端发来数据,服务器的很多资源就会被浪费。

3 发送HTTP请求

请求报文有请求行,请求头,请求体组成

请求行大概长这样

GET/images/logo.gif HTTP/1.1
           

请求行包含请求方法,URL,协议

请求方法:GET,POST,PUT,DELETE,HEAD,OPTIONS,TRACE,PATCH

请求头

请求头包含请求的附加信息,有关键字/值对组成,关键字和值用英文冒号":"分隔.

请求头部通知服务器关于客户端请求的信息,它包含许多有关客户端环境和请求正文的有用信息。使用keepalive,保持持久连接,一个连接可以发送多个请求.等

请求体

可以承载请求参数的数据,包含回车符,换行符和请求数据

4 服务器处理请求返回HTTP响应报文

主要讲HTTP的响应报文

包含协议版本,状态码,状态码描述

响应行:协议版本,状态码,状态码描述

响应头部:响应报文的附加信息,有名/值对组成

响应主题包含回车符,换行符,响应返回数据

4 浏览器解析渲染页面

浏览器渲染页面一共有五个步骤

  • 根据HTML解析出DOM树
  • 根据CSS解析生成CSS规则树
  • 结合DOM树和CSS规则树,生成渲染树
  • 根据渲染树计算每一个节点的信息
  • 根据计算好的信息绘制页面

1.根据 HTML 解析 DOM 树

  • 根据 HTML 的内容,将标签按照结构解析成为 DOM 树,DOM 树解析的过程是一个深度优先遍历。即先构建当前节点的所有子节点,再构建下一个兄弟节点。
  • 在读取 HTML 文档,构建 DOM 树的过程中,若遇到 script 标签,则 DOM 树的构建会暂停,直至脚本执行完毕。

2.根据 CSS 解析生成 CSS 规则树

  • 解析 CSS 规则树时 js 执行将暂停,直至 CSS 规则树就绪。
  • 浏览器在 CSS 规则树生成之前不会进行渲染。

3 结合 DOM 树和 CSS 规则树,生成渲染树

  • DOM 树和 CSS 规则树全部准备好了以后,浏览器才会开始构建渲染树。
  • 精简 CSS 并可以加快 CSS 规则树的构建,从而加快页面相应速度。

4 根据渲染树计算每一个节点的信息(布局)

  • 布局:通过渲染树中渲染对象的信息,计算出每一个渲染对象的位置和尺寸
  • 回流:在布局完成后,发现了某个部分发生了变化影响了布局,那就需要倒回去重新渲染。

5 根据计算好的信息绘制页面

  • 绘制阶段,系统会遍历呈现树,并调用呈现器的“paint”方法,将呈现器的内容显示在屏幕上
  • 重绘:某个元素的背景颜色,文字颜色等,不影响元素周围或内部布局的属性,将只会引起浏览器的重绘。
  • 回流:某个元素的尺寸发生了变化,则需重新计算渲染树,重新渲染。

5 断开链接 :TCP四次挥手

从URL输入到页面展示发生了什么
  • 客户端向服务器发送报文Fin=1,seq=u表示已经没有数据传输,并进入FIN-WAIT-1(终止等待1)状态。 (第一次挥手:客户端发起,发送给浏览器的)
  • 服务器发送报文ACK=1 seq=v ack=u+1 表示同意关闭请求,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)

    (第二次挥手:有服务器发起,告诉浏览器,我请求报文接受完了,我准备关闭,你也准备吧)

  • 服务器向客户端发送报文 Fin,ACK等请求关闭连接,进入LAST_ACK状态(最后确认状态)

    (第三次挥手:由服务器发起来的,告诉客户端,我的响应报文发送完了,你准备关闭吧)

  • 客户端向服务器发送报文段,然后进入TIME_WAIT状态,服务器收到请求后就关闭连接,客户端等待一段时间未收到回复,就正常关闭(第四次挥手:由客户端发起,告诉服务器,我响应报文接受完了,我准备关闭,你也关闭吧)

为什么客户端在TIME_WAIT状态必须当代2MSL的时间

1 为了保证客户端发送的最后一个ACK报文段能够到达服务器,这个ACK报文段有可能丢失,因为使处于LAST-ACK状态的服务器收不到对方发送的FIN+ACK报文段,服务器会超时重传FIN+ACK这个报文段,而客户端就能在2MSL时间内收到这个报文,然后重传,重新启动2MSL计时器,最后,客户端和服务器都正常进入到CLOSED状态。

如果客户端没有等待一段时间,就无法收到服务器发送的重传报文,因而不会再次发送去确认报文,那么服务器就无法按照正常步骤进入CLOSED状

2 防止已失效连接请求报文段,出现在本连接中,客户端发送完最后一个ACK报文后,再经时间2MSL,就可以是本地连接持续的时间内所产生的所有报文都从网络中消失,这样就不会在下一个新连接中出现失效的连接请求报文

为什么连接的时候是三次握手,关闭的时候却是四次握手?

因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

为什么不能用两次握手进行连接?

3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。

如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75分钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。