前端浏览器输入URL后发生什么?个人笔记

该题是一道特别经典的面试题了,涉及到前端人员应该掌握的基础网络知识,相信很多前端小伙伴都了解。网上也有很多相关文章介绍这方面的知识,我呢趁着最近项目不忙,就自己做了一篇笔记,这篇笔记是我这两天看了数十篇文章总结出来的,感觉比之前理解更透彻了,总结就是一个学习的过程,希望我的理解对大家有帮助。

浏览器输入URL之后大致有这么几个阶段:

  • DNS域名解析
  • 建立TCP连接
  • 发送HTTP请求
  • 服务端处理请求
  • 服务端返回响应结果
  • 关闭TCP连接
  • 浏览器解析HTML并渲染布局

DNS域名解析

我们访问一个网站的时候,可以通过主机名或者域名来访问。但是绝大多数的时候是使用域名来访问网站。因为相对于主机名的ip地址,域名更能让人记住。

但是TCP/IP协议是通过IP地址来访问的,所以就需要一个机制,将域名转换为IP地址

而DNS服务就是做这件事情,它提供了域名到IP地址之间的解析服务

当客户端收到你输入的域名地址后,它首先去找本地的hosts文件,检查在该文件中是否有相应的域名、IP对应关系,如果有,则向其IP地址发送请求,如果没有,再去找DNS服务器。一般用户很少去编辑修改hosts文件。

DNS服务器层次结构

DNS服务器迭代查询和递归查询

DNS解析过程

浏览器客户端向本地DNS服务器发送一个含有域名www.mybj123.com的DNS查询报文。

本地DNS服务器把查询报文转发到根DNS服务器,根DNS服务器注意到其com后缀,于是向本地DNS服务器返回comDNS服务器的IP地址。

本地DNS服务器再次向comDNS服务器发送查询请求,comDNS服务器注意到其www.mybj123.com后缀并用负责该域名的权威DNS服务器的IP地址作为回应。

最后,本地DNS服务器将含有www.mybj123.com的IP地址的响应报文发送给客户端。

从客户端到本地服务器属于递归查询,而DNS服务器之间的交互属于迭代查询。

正常情况下,本地DNS服务器的缓存中已有comDNS服务器的地址,因此请求根域名服务器这一步不是必需的。

DNS的优先级

本地电脑会将一些经常使用的域名和对应的IP地址建立一个映射关系,并保存到本地host文件中。当DNS解析的时候,会优先从本地host文件中查找映射的IP地址映射

  1. 如果在本地host文件中找到了域名对应的IP地址映射,会直接使用host文件中的IP地址
  2. 如果在本地host文件中没有找到域名对应的IP地址映射,会从本地DNS服务器中查找
  3. 如果在本地DNS服务器中也没有找到域名对应的IP地址映射,会继续向上一级的DNS服务器发送请求,直到DNS根服务器。如果找到,就进行回传,返回给浏览器。

建立TCP链接

先了解一个知识点:TCP/IP协议族

TCP/IP协议族是由四层协议组成的系统。分别是:

  • 应用层(http)
  • 传输层(tcp)
  • 网络层(ip)
  • 链路层(网络硬件)

建立TCP链接

我的理解是:我们访问一个网站之前,首先要保证有网络对吧?有网线/路由器对吧?那么此时,链路层就是ok的。经过上面第一步,已经知道了该域名映射的IP地址,并且可以访问,那么此时网络层也是ok的

那么接下来,就是传输层,也就是TCP。其实这里说的也不是很严谨,传输层不仅仅是TCP一种协议,还有UDP协议。UDP协议是无连接的,因为其不需要连接,所以效率比较高,但是也是因为不需要连接验证所以安全性和可靠性得不到保障。而TCP是面向连接的,有校验机制。所以用的较广泛。但是也有缺点:因为提前建立了连接,所以效率就较低。本文说的传输层指的是TCP协议

为了确保连接双方的可靠性,在双方建立连接时,TCP采用了三次握手策略

三次握手策略

上图理解为:

客户端发送一个带有SYN标志的数据包给服务端,服务端收到后,回传一个带有SYN/ACK标志的数据包以示传达确认信息,最后客户端再回传一个带ACK标志的数据包,代表握手结束,连接成功。

上图也可以这么理解:

客户端:“你好,在家不,有你快递。”

服务端:“在的,送来就行。”

客户端:“好嘞。”

知其然更要知其所以然,为什么要进行三次握手才能建立TCP连接?

根本原因就是为了确保客户端和服务端双方的接收和发送能力都是ok的

经过第一次握手后,服务端收到了客户端的SYN请求标志,那么此时服务端就可以知道:客户端的发送能力是ok的,服务端本身自己的接收能力是ok的

经过第二次握手后,客户端收到了服务端的SYN+ACK请求+返回标志,那么此时,客户端就可以知道:客户端本身的发送和接收能力是ok的,服务端的发送和接收能力有是ok的

经过第三次握手后,服务端接收到了客户端的ACK返回标志,那么此时,服务端就可以知道:服务端本身自己的接收和发送能力是ok的

发送HTTP请求

建立TCP连接之后,就可以发送HTTP请求了。说到HTTP请求,那么前端同学就不得不了解下关于HTTP报文的相关知识点。

发送HTTP请求

这样看不怎么直观,我们可以通过curl(命令行网络测试工具)来测试发起请求的报文结构。这里我们以百度为例。

打开终端,输入curl -v www.baidu.com,可以看到:

发送HTTP请求

上方截图的请求报文旁边空白比较少,单独拎出来讲一下:

GET / HTTP/1.1 // 请求行 (方法/路径/协议)

// 以下是请求头
Host: www.baidu.com
User-Agent:curl/7.54.0
Accept: */*
// 空行

// 请求体 因为没有任何参数 所以是空的

这里我整理一些常用的报文头。

请求头和响应头都属于报文头

常用报文头

  1. Accept: 客户端可以接受的媒体类型
    Accept:text/html: 表示浏览器可以接受服务器返回的类型是tetx/html。也就是常说的 html 文档 但是如果服务器无法返回text/html类型的数据,服务器应该返回一个406(Non Acceptable)错误
    Accept:*\*: 代表浏览器可以处理所有类型
    – 如果想要给显示的媒体类型增加优先级 则可以使用q=?来额外表示权重。权重q的范围是0~1, 权重 q 默认是 1
  2. Accept-Encoding: 浏览器申明自己的编码方法
    – 通常指定压缩方法 是否支持压缩 支持什么压缩方法(gzip / deflate)
  3. Accept-Language: 浏览器申明自己的语言
    Accept-Language:zh-cn,zh;q=0.7,en-us,en;q=0.3
    – 也可以指明权重信息
  4. Connection:keep-alive
    – 当一个网页打开完成后,客户端和服务端之间用于传输 HTTP 数据的 TCP 连接不会关闭,注意是 TCP 连接。这样做的好处是 避免多次的 3 次握手和 4 次挥手
    Connection:close
    – 当一个网页打开完成后,客户端和服务端之间用于传输 HTTP 数据的 TCP 连接会关闭
    – 当客户端再次发送请求时,需要重新建立TCP连接
  5. Host: 被请求资源的 Interent 主机名和端口号
    – 它通常从 URL 中提取出来
    – www.xxx.com:8080
  6. Referer: 来源
    – 用于告知服务器是从哪个链接进来的,服务器借此可以获得一些信息用于处理
  7. User-Agent: 告诉服务器 客户端使用的操作系统的名称和版本
    – 服务端可以通过User-Agent来判断浏览器类型,作出不同的兼容处理
  8. Content-Type: 说明报文体内对象的媒体类型
    text/html:HTML 格式
    text/plain:纯文本格式
    text/xml:XML 格式
    image/gif:gif 图片格式
    text/jpeg:jpg 图片格式
    text/png:png 图片格式
    application/json:JSON 数据格式
    application/xxml:XML 数据格式
    application/msword:Word 文档格式
    application/octet-stream:二进制数据流(常见于文件下载)
    application/x-www-form-urlencoded:表单提交

服务器处理请求

服务器端收到请求后的由web服务器(准确说应该是http服务器)处理请求,诸如Apache、Ngnix、IIS等。web服务器解析用户请求,知道了需要调度哪些资源文件,再通过相应的这些资源文件处理用户请求和参数,并调用数据库信息,最后将结果通过web服务器返回给浏览器客户端。

服务器处理请求

返回响应结果

在HTTP里,有请求就会有响应,哪怕是错误信息。这里我们同样看下响应报文的组成结构:

返回响应结果

在响应结果中都会有个一个HTTP状态码,比如我们熟知的200、301、404、500等。通过这个状态码我们可以知道服务器端的处理是否正常,并能了解具体的错误。

状态码由3位数字和原因短语组成。根据首位数字,状态码可以分为五类:

  • 1xx: 指示信息 – 表示请求已接受,但是需要继续处理 临时响应
  • 2xx: 成功 – 表示请求已被成功接收
  • 3xx: 重定向 – 要完成请求必须进行更进一步的操作
  • 4xx: 客户端错误 – 请求有语法错误或请求无法实现
  • 5xx: 服务器错误 – 服务器未能实现合法的请求

常用状态码

  • 200 OK:客户端请求成功
  • 202 Accepted: 已接受 已经接受请求 但是未处理完成
  • 206 Partial Content断点续传 客户发送了一个带有 Range<范围>头的 GET 请求,服务器完成了 它 <请求视频或者音频文件很大的时候 服务器就会给你返回部分[Range] 的文件>
  • 301 Moved Permanently:所请求的页面已经转移至新的 url <永久重定向>
  • 302 Found:所请求的页面已经临时转移至新的 url <临时重定向>
  • 304 Not Modified之前缓存可用 客户端有缓存的文档并发出了一个条件性的请求,服务器告诉客户端,原来缓存的文档还可以继续使用
  • 400 Bad Request:客户端请求语法错误,不能被服务器所理解
  • 401 Unauthorized:请求未经授权 要求用户的身份认证,这个状态码必须和 WWW-Authenticate 报头域一起使用
  • 403 Forbidden: 服务器理解请求客户端的请求,但是拒绝执行此请求
  • 404 Not Found请求资源不存在
  • 500 Internal Server Error:服务器内部错误,无法完成请求
  • 502 Bad Gateway网关或代理的服务器发生了错误 从远端服务器接收到了一个无效的请求
  • 503 Server Unavailable请求未完成,服务器临时过载或宕机,一段时间后可能恢复正常

关闭TCP连接

为了避免服务器与客户端双方的资源占用和损耗,当双方没有请求或响应传递时,任意一方都可以发起关闭请求。与创建TCP连接的3次握手类似,关闭TCP连接,需要4次握手

4次握手

TCP四次挥手断开连接

经过之前的三次握手客户端和服务端都进入了ESTAB-LISHED状态

  1. 第一次挥手客户端发送带有FIN标志的断开连接请求报文段,然后客户端就进入了FIN-WAIT-1状态(终止等待状态1)等待服务器确认
  2. 第二次挥手服务端接收到了客户端浏览器发送的FIN标志报文段后,需要发送ACK确认报文段对这个FIN报文段进行确认,此时服务端进入CLOSE-WAIT状态(关闭等待状态)。客户端收到该ACK却报文段后,客户端就进入了FIN-WAIT-2状态(终止等待状态2)。(此时客户端向服务端的TCP连接已经关闭。但是服务端向客户端的TCP连接还没有关闭)
  3. 第三次挥手等待服务端已经没有任何数据发送给客户端之后,服务端会向客户端发送FIN+ACK报文段(关闭+确认)。然后服务端进入到LAST-ACK状态(最后确认状态)
  4. 第四次挥手客户端向服务端发送ACK确认标志。服务端收到该确认信息后进入到CLOSED状态(TCP关闭状态)。客户端在等待2MSL(报文最大生存时间)时间后,也进入到了CLOSED状态(TCP关闭状态)。此时四次挥手成功,客户端和服务端双方都已关闭TCP连接

上图如果实在理解不了大家也可以这么理解:

客户端:“兄弟,我这边没数据要传了,咱关闭连接吧。”

服务端:“收到,我看看我这边有木有数据了。”

服务端:“兄弟,我这边也没数据要传你了,咱可以关闭连接了。”

客户端:“好嘞。”

面试中关于四次挥手经常问到的是:为什么最后客户端会等待一段时间之后才会进入关闭状态?

因为最后一次挥手客户端发送给服务端的确认信息,服务端可能会没有收到。那么如果服务端没有收到客户端发送的最后确认信息,那么服务端会认为我本身发送给客户端的关闭请求因为客户端没有收到该请求,所以客户端才没有给我发送确认信息,我才会收不到。所以服务端会再次向客户端发送该关闭请求。为了避免客户端真的没有收到服务端的关闭请求,客户端会等待一段时间(报文最大生存时间)之后,再进入关闭状态

浏览器解析HTML并渲染布局

客户端浏览器在收到服务端的响应结果后,就要开始解析并渲染了,

webkit引擎渲染大致过程:

webkit引擎渲染大致过程

  1. HTML 经过 HTML Parser 转成 DOM Tree(DOM 树)
  2. CSS 按照 CSS 规则和 CSS Parser 转成 CSS Tree
  3. DOM TreeCSS Tree 结合形成 Render Tree
  4. 通过Layout精确的计算出要显示的DOM真正的位置
  5. 浏览器通过Paint显示出最终的页面效果

这其中有几个经常会被问到的面试题

什么是重绘(Repaint)?

重绘就是Repaint,是在一个元素的外观被改变,但没有改变布局(改变元素的非几何属性)的情况下发生的,如改变了visibilityoutlinebackground等。当repaint发生时,浏览器会验证DOM树上所有其他节点的visibility属性。

当各种盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来以后,浏览器便把这些元素都按照各种的特性绘制一遍,于是页面的内容就出现了,这个过程称之为repaint

如何触发重绘(Repaint)?

改变元素非几何属性(外观属性)。如:color background-color等

什么是重排(Reflow)?

DOM结构中的各个元素都有自己的盒子(模型),这些都需要浏览器根据各种样式来计算并根据计算结果将元素放到它该显示的位置(改变元素的几何属性),这个过程称之为reflow

如何触发重排(Reflow)?

  1. 增加、删除、修改DOM节点时 会导致Reflow或Repaint
  2. 移动DOM的位置 或者DOM动画的时候
  3. 修改CSS样式的时候
  4. Resize窗口大小的时候(移动端没有这个问题),或是滚动的时候 都有可能触发Reflow
  5. 修改网页的默认字体的时候

减少Reflow对性能的影响的建议?

Reflow(回流)是导致DOM脚本执行效率低的关键因素之一,页面上任何一个节点触发了Reflow,会导致它的子节点及祖先节点的重新渲染

  1. 不要一条一条地修改DOM的样式,预先定义好 class,然后修改 DOMclassName
  2. 把 DOM离线后再修改,比如:先把 DOMdisplay:none (有一次 Reflow),然后修改 100 次后,然后再把它 display:block
  3. 不要把 DOM节点的属性值放在一个循环里当成循环里的变量
  4. 尽可能不修改影响范围比较大的 DOM
  5. 为动画的元素使用定位 absolute / fixed
  6. 慎重选择高消耗的样式,比如有: box-shadows | border-radius | transparency | transforms |CSS filters(性能杀手)
  7. 不要使用 table 布局,可能很小的一个小改动会造成整个 table的重新布局

重排和重绘的关系?

重排必定会引发重绘,但重绘不一定会引发重排

结语

以上就是今天码云笔记为大家整理的关于前端浏览器输入URL后发生什么的个人学习笔记,文章有点长,但是干货满满,这个也是前端面试常问的经典面试题,作为一个前端开发是必知的知识。可能有些整理的不全,但是后期还会更新,也欢迎大家拍砖。

1. 本站所有免费资源来源于用户上传和网络,因此不包含技术服务请大家谅解!如有侵权请邮件联系客服!
2. 本站不保证所提供下载的免费资源的准确性、安全性和完整性,免费资源仅供下载学习之用!如有链接无法下载、失效,请联系客服处理!
3. 您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容资源!如用于商业或者非法用途,与本站无关,一切后果请用户自负!
4. 如果您也有好的资源或技术教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
5. 加入前端开发QQ群:565733884,我们大家一起来交流技术!
码云笔记 » 前端浏览器输入URL后发生什么?个人笔记

发表评论