从浏览器输入一个url到页面渲染

1. URL解析: 检验合法性,对不合法的进行转义。提取domain name

在浏览器搜索框内部数据URL,在输入过程中,浏览器地址栏会根据历史访问、收藏书签、最近搜索记录等,及时弹出输入建议。
在URL输入完成回车后,浏览器开始对URL进行解析,主要做三件事:URL格式校验、关键字解析、字符校验与转义。

合法得URL格式,大致有以下几部分:

http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument

<scheme>://<host>.<domain>:<port>/<path>?<params>#<anchor>

  • scheme —— 定义因特网服务的类型。最常见的类型是http
  • host —— 定义域主机(http的默认主机是 www
  • domain —— 定义因特网域名,比如example.com
  • :port —— 定义主机上的端口号是80
  • path —— 是网络服务器上资源的路径/path/to/myfile.html
  • ?<params> —— ?key1=value1&key2=value2 是提供给网络服务器的额外参数。 这些参数是用 & 符号分隔的键/值对列表。在返回资源之前,Web服务器可以使用这些参数来执行额外的操作。每个Web服务器都有自己关于参数的规则,唯一可靠的方式来知道特定Web服务器是否处理参数是通过询问Web服务器所有者。
  • #<anchor> —— #SomewhereInTheDocument是资源本身的另一部分的锚点. 锚点表示资源中的一种“书签”,给浏览器显示位于该“加书签”位置的内容的方向。例如,在HTML文档上,浏览器将滚动到定义锚点的位置;在视频或音频文档上,浏览器将尝试转到锚代表的时间。值得注意的是,#后面的部分(也称为片段标识符)从来没有发送到请求的服务器。

URL关键字解析:当协议或主机名不合法时,也就是不符合 URL 格式,比如输入几个单词,中文等。浏览器会将地址栏中输入的文字传给默认的搜索引擎。我就经常用 Chrome 的此特性快速 google 搜索。

字符校验:URL 为了在不同协议不同传输机制都可以安全的运送信息,采用的字符都是符合 ASCII 集的。这其中还包含一些保留字符,比如上面的 URL 协议中的分割字符,等特殊含义的字符。而不安全的字符,非 ASCII 的 Unicode(中文等) 字符,就会通过转义去处理,使用 % 。

HSTS 列表
HSTS 就是HTTP 严格传输安全(HTTP Strict Transport Security)的缩写,是为了让浏览器强制使用 HTTPS 访问的,更具体的内容参考什么是HSTS,为什么要使用它?。当你的网站均采用 HTTPS,并符合它的安全规范,就可以申请加入HSTS 列表,之后用户不加 HTTPS 协议再去访问你的网站,浏览器都会定向到 HTTPS。无论匹配到没有,都要开始 DNS 查询工作了。

2. DNS解析: 转化域名为TCP连接使用的ip地址

浏览器从URL中提取出domain name后,开始进行进行DNS解析。

为什么要 DNS 解析?
因为 http 是基于 tcp 连接的,而 tcp 则是通过 ip 地址去识别访问的。DNS 解析就是域名转化成服务器ip 地址的过程。

DNS 查询过程
域名通过 DNS 转化成 ip 地址的过程。

1. 查看浏览器内部缓存、系统缓存

检测域名是否存在于浏览器缓存中(打开 chrome://net-internals/#dns 即可查看本机浏览器的 dns 缓存)。如果有缓存直接使用,没有则浏览器会调用一个类似 gethostbyname 的库函数,此函数会先去检测本地 hosts 文件,查在该文件中是否有相应的域名、IP对应关系,如果有,则向其IP地址发送请求,如果没有,向DNS服务器发送查询请求。

2.路由器缓存、ISP DNS缓存

如果浏览器和系统缓存都没有,系统的 gethostname 函数就会向本地DNS服务器发送请求(本地DNS服务器一般都是你的网络接入服务器商提供,比如中国电信,中国移动)。而网络服务在经过路由器以及网络服务商,所以会先查询路由器缓存,然后再查询 ISP 的 DNS 缓存。

3. 本地 DNS 服务器

查询你输入的网址的DNS请求到达本地DNS服务器之后,本地DNS服务器会首先查询它的缓存记录,如果缓存中有此条记录,就可以直接返回结果,此过程是递归的方式进行查询。如果没有,本地DNS服务器还要向DNS根服务器进行查询。

5. 域名服务器

本地DNS服务器迭代查询:

根域服务器(.) -> 顶级域名服务器(eg: .com,.org)-> 主域名服务器(eg: cnblogs.com)->本地NDS服务器收到域名和IP地址对应关系

本地DNS服务器收到一个域名和IP地址对应关系,本地DNS服务器不仅要把IP地址返回给用户电脑,还要把这个对应关系保存在缓存中,以备下次别的用户查询时,可以直接返回结果,加快网络访问。
DNS查询过程

3. TCP连接

DNS域名解析获取到IP地址后,便会开始建立一次连接,这是由TCP协议完成。

TCP报文段的头部结构
在了解TCP连接之前先来了解一下TCP报文的头部结构:
在这里插入图片描述上图中有几个字段需要重点介绍下:

(1)序列号(sequence number):seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。

(2)确认号(acknowledgement number):ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ack=seq+1。

(3)标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:

  • SYN:同步标识,发起一个新连接。在“三次握手”的前两次出现。TCP 协议规定,SYN = 1 时,当前 TCP 段不能携带其他有效数据。
  • ACK:确认标识,接收端确认接收到数据。TCP 协议规定,只有 ACK = 1 时有效,即确认号信息才会包含在 TCP 段内,反正为 0。
  • FIN:结束标识,释放一个连接。表示双方数据发送完成,跟SYN 类似,属于行为标识。也是 FIN = 1 时,TCP 段内不能包含其他主体数据。。
  • PSH:接收方应该尽快将这个报文交给应用层。
  • RST:重置连接。
  • URG:紧急指针(urgent pointer)有效。

需要注意的是:

  • 不要将确认序号ack与标志位中的ACK搞混了。
  • 确认方ack=发起方seq+1,两端配对。

TCP三次握手:目的建立一个连接

TCP三次握手:本质是确认通信双方收发数据的能力

  • 第一次握手:“喂,你听得到吗?”
    客户端要向服务端发起连接请求,首先客户端随机生成一个起始序列号ISN=x,那客户端向服务端发送的报文段:SYN=1 & seq = x
  • 第二次握手:“我听得到呀,你听得到我吗?”
    • 服务端收到客户端发过来的报文:SYN=1 & seq=x,发现SYN=1为一个连接请求,于是将客户端的起始序列号x=100存起来,并且随机生成一个服务端的起始序列号seq=y
    • 服务端向客户端回复一段报文:SYN=1 & ACK=1 & seq=y & ack=x+1
  • 第三次握手:“我能听到你,今天balabala……”
    • 客户端收到服务端的回复后发现ACK=1 & ack=x+1,于是知道服务端已经收到了序列号为100的那段报文;
    • 发现SYN=1,知道服务端同意本次连接,保存服务端的序列号y=300
    • 客户端再回复一段报文给服务端:ACK=1 & seq=x+1 & ack=y+1。(第一次握手时发送报文是占据一个序列号的,这次seq就从x+1开始:因为是不携带数据的ACK报文是不占据序列号的,后面第一次正式发送数据时seq也还是x+1)。
    • 当服务端收到报文后发现ACK=1并且ack=y+1,就知道客户端收到序列号seq=y的报文,就这样客户端和服务端通过TCP建立了连接。
      在这里插入图片描述

四次挥手:目的是关闭一个连接

TCP 数据传输完,是要断开连接的。我说的数据传输完,是某一端发送完数据,要断开连接,去发送一个断开的请求,客户端和服务端都可以主动断开连接。为什么断开要四次呢。

假设客户端初始化的序列号ISA=x,服务端初始化的序列号ISA=y。TCP连接成功后客户端总共发送了N个字节的数据,服务端在客户端发FIN报文前总共回复了M个字节的数据。

  • 第一次挥手:当客户端的数据都传输完成或未完成时,客户端向服务端发出连接释放报文,释放连接报文:FIN=1 & seq=u = x + N + 1 (其中的1是建立连接时占的一个序列号)。需要注意的是客户端发出FIN报文段后只是不能发数据了,但是还可以正常收数据;另外FIN报文段即使不携带数据也要占据一个序列号。
  • 第二次挥手:服务端收到客户端发的FIN报文后给客户端回复确认报文:ACK=1 & ack= u+1 & seq= v = M+y。此时服务端处于关闭等待状态,而不是立马给客户端发FIN报文,这个状态还要持续一段时间,因为服务端可能还有数据没发完。
  • 第三次挥手:服务端将最后数据(比如Q个字节)发送完毕后就向客户端发出连接释放报文:FIN=1 & ACK=1 & ack=u+1 & seq= w = v+Q
  • 第四次挥手:客户端收到服务端发的FIN报文后,向服务端发出确认报文: ACK=1 & ack=w+1 & seq= u+1。注意客户端发出确认报文后不是立马释放TCP连接,而是要经过2MSL(最长报文段寿命的2倍时长)后才释放TCP连接。而服务端一旦收到客户端发出的确认报文就会立马释放TCP连接,所以服务端结束TCP连接的时间要比客户端早一些。
    在这里插入图片描述

为什么TCP连接的时候是3次?2次不可以吗?

  • 主要考虑连接时丢包的问题
    • 如果只握手2次,第二次握手时如果服务端发给客户端的确认报文段丢失,此时服务端已经准备好了收发数据(可以理解服务端已经连接成功),而客户端一直没收到服务端的确认报文,所以客户端就不知道服务端是否已经准备好了(可以理解为客户端未连接成功),这种情况下客户端不会给服务端发数据,也会忽略服务端发过来的数据。
    • 如果是三次握手,即便发生丢包也不会有问题。如果第三次握手客户端发的确认ack报文丢失,服务端在一段时间内没有收到确认ack报文的话就会重新进行第二次握手,也就是服务端会重发SYN报文段,客户端收到重发的报文段后会再次给服务端发送确认ack报文。

为什么TCP连接的时候是3次,关闭的时候却是4次?

  • 因为只有在客户端和服务端都没有数据要发送的时候才能断开TCP。而客户端发出FIN报文时只能保证客户端没有数据发了,服务端还有没有数据发客户端是不知道的。而服务端收到客户端的FIN报文后只能先回复客户端一个确认报文来告诉客户端我服务端已经收到你的FIN报文了,但我服务端还有一些数据没发完,等这些数据发完了服务端才能给客户端发FIN报文(所以不能一次性将确认报文和FIN报文发给客户端,就是这里多出来了一次)。

为什么客户端发出第四次挥手的确认报文后要等2MSL的时间才能释放TCP连接?

  • 这里同样是要考虑丢包的问题,如果第四次挥手的报文丢失,服务端没收到确认ack报文就会重发第三次挥手的报文,这样报文一去一回最长时间就是2MSL,所以需要等这么长时间来确认服务端确实已经收到了。
    如果已经建立了连接,但是客户端突然出现故障了怎么办?
  • TCP设有一个保活计时器,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接

4. HTTP请求

建立TCP连接之后,浏览器发出http请求。一个HTTP请求报文由请求行(request line)、请求头(header)、空行和请求数据4个部分组成。 详细内容见http 协议在这里插入图片描述

5. 服务器处理http请求、浏览器接收http响应

服务器处理请求

服务器在收到浏览器发送的HTTP请求之后,会将收到的HTTP报文封装成HTTP的Request对象,并通过不同的Web服务器进行处理,web服务器解析用户请求,知道了需要调度哪些资源文件,再通过相应的这些资源文件处理用户请求和参数,并调用数据库信息,处理完的结果以HTTP的Response对象返回,主要包括状态码,响应头,响应报文三个部分。最后将结果通过web服务器返回给浏览器客户端。
在这里插入图片描述

浏览器接收http响应

服务器在收到浏览器发送的HTTP请求之后,会将收到的HTTP报文封装成HTTP的Request对象,并通过不同的Web服务器进行处理,处理完的结果以HTTP的Response对象返回,由四个部分组成:状态行、消息报头、空行和响应正文。 详细内容见http 协议

6. 页面渲染

浏览器解析:

浏览器需要加载解析的不仅仅是HTML,还包括CSS、JS。以及还要加载图片、视频等其他媒体资源。
在这里插入图片描述
浏览器

  • 解析HTML,构建DOM树:调用HTML解析器解析HTML标记为对应的 token并构建DOM关系树
  • 解析CSS,生成CSS规则树: 调用CSS解析器解析style/link标记
  • 解析script,遇见 script 标记 调用javascript引擎 处理script标记、绑定事件、修改DOM树/CSS树等
  • 合并DOM树和CSS规则,生成render树
  • 布局render树(Layout/reflow),负责各元素尺寸、位置的计算
  • 绘制renxder树(paint),绘制页面像素信息
  • 浏览器会将各层的信息发送给GPU,GPU会将各层合成(composite),显示在屏幕上
    在这里插入图片描述

布局渲染

要注意的是,浏览器的解析过程并非是串连进行的,比如在解析CSS的同时,可以继续加载解析HTML,但在解析执行JS脚本时,会停止解析后续HTML,这就会出现阻塞问题。

在浏览器还没接收到完整的HTML文件时,它就开始渲染页面了,在遇到外部链入的脚本标签或样式标签或图片时,会再次发送 HTTP 请求重复上述的步骤。在收到 CSS 文件后会对已经渲染的页面重新渲染,加入它们应有的样式,图片文件加载完立刻显示在相应位置。在这一过程中可能会触发页面的重绘或重排。这里就涉及了两个重要概念:Reflow和Repaint。
- Reflow,也称作Layout,中文叫回流,一般意味着元素的内容、结构、位置或尺寸发生了变化,需要重新计算样式和渲染树,这个过程称为Reflow。
- Repaint,中文重绘,意味着元素发生的改变只是影响了元素的一些外观之类的时候(例如,背景色,边框颜色,文字颜色等),此时只需要应用新样式绘制这个元素就OK了,这个过程称为Repaint。
- 所以说Reflow的成本比Repaint的成本高得多的多。DOM树里的每个结点都会有reflow方法,一个结点的reflow很有可能导致子结点,甚至父点以及同级结点的reflow。

7. 关闭TCP连接或继续保持连接

参考:

  • https://www.cnblogs.com/jin-zhe/p/11586327.html
  • https://www.jianshu.com/p/27862635c077
  • https://blog.csdn.net/ThinkWon/article/details/104903925
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值