前言
不说太多废话了,这个题目其实基本上是现在面试的高频考点了,现在我也想自己认认真真的捋一遍,到时候面试也可以流利的回答。
开始
let’s go
URL解析
其实有人一开始会有疑惑,至少我一开始也有疑惑,不是应该先DNS解析吗?
其实不是的,现在的浏览器他会优先解析你是不是一个合法的URL,为什么呢?比如我们在Chrome输入中文“Derrick是帅哥吗”,这样的不是一个正常的合法的URL,就会优先调用你默认的搜索引擎开始搜索。
当然了,合法的URL包括了协议和网络地址,最常用的协议是
- HTTP(超文本传输协议)
- FTP(文件传输协议)
网络地址也可以是ip地址,以及端口号,没有端口默认是80端口
DNS域名解析
这一步其实简单来说就是”baidu.com”这个域名,解析成一个整个的地址。
比如我们的家庭住址都有一个门牌号,xx小区xx栋xx号
这样的一串标识符就可以精准的找到我们的家庭住址,而每一个ip地址就是这样的一个门牌号,比如baidu.com
这个不是一个门牌号,这个可以理解为百度的家,你告诉浏览器你要去百度的家,这个时候就会开始进行DNS解析他会解析成百度的门牌号,然后找到百度的家。
缓存
这里面又会涉及到缓存的概念,什么意思呢?
就是之前我查过百度的家了,已经记录下来百度的家的门牌号了,就不需要重新的进行解析了,直接读取就好了,节约时间。
这里面涉及的知识太多了,不在这次的讨论范围内。所以只简单的说一下。
上图其实很好的解答了DNS的整个解析过程。
- 从浏览器获取缓存结果。
- 如果浏览器没有缓存就从本地系统的缓存中读取,比如host文件等等,像我们平常上GitHub如果慢的话我们都会修改host文件,给他配一个快一点的ip之类的等等。
- 然后是图里面没有提到的路由器缓存,一般的路由器也会有自己的缓存。
- 路由器也找不到只能开始解析了。本地域名服务器会向根域名服务器发送一个请求, 如果根域名服务器也不存在该域名时, 本地域名会向com顶级域名服务器发送一个请求, 依次类推下去。 直到最后找到目标网址所对应的 IP, 并将其缓存到本地, 以供下次使用。
DNS重定向
这里顺便说一下DNS的重定向吧
DNS每次返回的ip地址可能会不一样,因为世界上不是只有一个机器可以处理”baidu.com”的这个请求,有很多机器可以处理,DNS只需要返回可以处理的机器的ip地址就可以了。例如可以根据每台机器的负载量, 该机器离用户地理位置的距离等等, 这种过程就是DNS负载均衡, 又叫做DNS重定向。
很简单,几个例子,比如我在故宫的北门,打开地图要查询故宫肯定会让我从北门进去。而如果我在故宫的南门,要导航到故宫就会让我从南门进去。
DNS污染
DNS 污染(DNS cache pollution), 又称域名服务器缓存投毒(DNS cache poisoning), 是指一些刻意制造或无意中制造出来的域名服务器数据包, 把域名指往不正确的IP地址。
某些网络运营商为了某些目的, 对DNS进行了某些操作, 导致上网的用户无法通过域名取得正确的IP地址。 某些国家或地区出于某些目的为了防止某网站被访问, 而且其又掌握部分国际DNS根目录服务器或镜像, 也会利用此方法进行屏蔽。 (Google、 Facebook等)
至于如果防止DNS污染, 这里只说一个方法就是修改hosts文件, 其他的自行搜索吧。
TCP建立连接
其实我们解析之后,找到真正的服务器,我们就需要获取他的资源,最简单的就是获取他的HTML文件,来渲染对吧?怎么获取呢,我们需要TCP连接来获取。
这里涉及到三次握手,和四次挥手以及UDP的一些细一点的知识点。
说TCP之前我想把一些里面可能用到的东西先说说清楚,方便查找。
位码即tcp标志位,有6种标示:SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急)Sequence number(顺序号码) Acknowledge number(确认号码)
三次握手
三次握手基本上就是👆的图片了,里面的位码在之前也有解释。
这里重点说一下为什么是三次握手🤝,而不是两次或者四次。
A在街上看见了隔了100米的B,(正常情况下如果面对面交流是没有问题的,但是街上很吵,各种车鸣声,店铺广告声之类的。)所以A想和B进行对话,(别问题为什么不打电话,节约钱!)
A喊了B一声,不知道B听不听得见,所以只能在远处等B的回应。
B听见了,也回应了A,但是他不知道A能不能听见所以也要等A回应。
然后A给出了回应,之后A和B就快乐的交流起来。
ok,我们再概括一下。
对应到三次握手就是A -> client;B->server
- 第一次🤝(A喊B)是为了确认一下B能不能听见,也就是客户端要确认服务端的接受功能正不正常
- 第二次🤝(B喊A)是告诉A,我能听见,现在我现在知道你能不能听见,也就是服务端告诉客户端我接受功能正常,现在我想知道你接收功能正不正常。
- 第三次🤝(A喊B)是为了告诉B我听见了,也就是客户端让服务端知道客户端的接收功能正常,并且可以开始传输。
为什么要三次握手,因为只有这三次可以完美的确认双方的接收和发送功能正常。
为什么不是两次握手?按照上面的说法,B直接开始发送数据,可是他根本不知道A能不能接收啊,发出去岂不是浪费了,对吧?万一A不能接收呢?所以只能等待A的回应
为什么不是四次握手?因为三次就已经完成了他们互相想知道的信息不需要继续浪费资源了,赶紧开始通信吧!
四次挥手
四次挥手其实后面才会讲到,但是因为知识点是一起的,所以就放在一起讲了
老规矩,看图和上面的位码意思,就不多解释了。
这里重点解释一下为什么是四次挥手👋
看图我们可以很明显的看到其实就多了一次服务端告诉客户端要终止的消息。
还是举刚刚A和B的例子吧。
A觉得和B聊的差不多了,想结束对话,因为天色很晚了要回家吃饭🍚了。
所以A告诉B,我想走了,不想聊了。
B收到后告诉A,好的,我知道了,但是你等我一下,我撒泡尿,撒完一起走。
B撒完尿之后,告诉A我撒完尿了。
A收到两句话(1.B听到👂A想回家的消息,2.B撒完尿之后的一句话)后,告诉B,我走了。
B听到后也回家了。
ok,我们再概括一下。
对应到三次握手就是A -> client;B->server
- 第一次👋 A告诉B我想回家吃饭了。也就是客户端告诉服务端,想断开连接了。
- 第二次👋B告诉A我收到你的消息了,不过我尿拉完就一起回家吧。也就是服务端告诉客户端我收到你的消息了,但是我这里还有一个文件没有传输完,搞定了就关闭链接。
- 第三次👋B告诉A我撒完尿了。也就是服务端告诉客户端我文件传输完了,可以关闭链接了。
- 第四次👋A告诉B你的两句话都听到了(1.B听到了A想回家的消息,2.B撒完尿了)。也就是客户端告诉服务端我关闭链接了,你也别发了。
双方结束链接。
相比于三次握手,多出来的那一次回收就是服务端需要有一个关闭传输的这么一个过程,这个过程可能需要时间,所以客户端需要等待传输。
UDP
这里虽然不在范围内,但是我想讲都讲了,顺便吧UDP一起说吧!
UDP协议全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。
它有以下几个特点:
1.面向无连接
首先 UDP 是不需要和 TCP一样在发送数据前进行三次握手建立连接的,想发数据就可以开始发送了。并且也只是数据报文的搬运工,不会对数据报文进行任何拆分和拼接操作。
具体来说就是:
- 在发送端,应用层将数据传递给传输层的 UDP 协议,UDP 只会给数据增加一个 UDP 头标识下是 UDP 协议,然后就传递给网络层了
- 在接收端,网络层将数据传递给传输层,UDP 只去除 IP 报文头就传递给应用层,不会任何拼接操作
2.有单播,多播,广播的功能
UDP 不止支持一对一的传输方式,同样支持一对多,多对多,多对一的方式,也就是说 UDP 提供了单播,多播,广播的功能。
3.UDP是面向报文的
发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。因此,应用程序必须选择合适大小的报文
4.不可靠性
首先不可靠性体现在无连接上,通信都不需要建立连接,想发就发,这样的情况肯定不可靠。
并且收到什么数据就传递什么数据,并且也不会备份数据,发送数据也不会关心对方是否已经正确接收到数据了。
再者网络环境时好时坏,但是 UDP 因为没有拥塞控制,一直会以恒定的速度发送数据。即使网络条件不好,也不会对发送速率进行调整。这样实现的弊端就是在网络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景(比如电话会议)就需要使用 UDP 而不是 TCP。
UDP只想把数据发出去,具体有没有成功他不关心
5.头部开销小,传输数据报文时是很高效的。
UDP 头部包含了以下几个数据:
- 两个十六位的端口号,分别为源端口(可选字段)和目标端口
- 整个数据报文的长度
- 整个数据报文的检验和(IPv4 可选 字段),该字段用于发现头部信息和数据中的错误
因此 UDP 的头部开销小,只有八字节,相比 TCP 的至少二十字节要少得多,在传输数据报文时是很高效的
6.总结
UDP | TCP | |
---|---|---|
是否连接 | 无连接 | 面向连接 |
是否可靠 | 不可靠传输,不使用流量控制和拥塞控制 | 可靠传输,使用流量控制和拥塞控制 |
连接对象个数 | 支持一对一,一对多,多对一和多对多交互通信 | 只能是一对一通信 |
传输方式 | 面向报文 | 面向字节流 |
首部开销 | 首部开销小,仅8字节 | 首部最小20字节,最大60字节 |
适用场景 | 适用于实时应用(IP电话、视频会议、直播等) | 适用于要求可靠传输的应用,例如文件传输 |
SSL/TLS加密
在HTTP请求之前,如果有加密的(就是HTTPS),需要先确认一下双方是否是自己想要找的那个人。
怎么知道那个他是不是自己要找的人呢?有两种方法:对称加密和非对称加密
对称加密
对称加密其实就是A和B都有一个解密的规则,双方都心知肚明。这样就可以解密。
对称加密的一大缺点是密钥的管理与分配,换句话说,如何把密钥发送到需要解密你的消息的人的手里是一个问题。在发送密钥的过程中,密钥有很大的风险会被黑客们拦截。现实中通常的做法是将对称加密的密钥进行非对称加密,然后传送给需要它的人。
非对称加密
那么什么是非对称加密呢?
非对称加密为数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥,公钥(public key)和私钥(private key)。私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥。比如,你向银行请求公钥,银行将公钥发给你,你使用公钥对消息加密,那么只有私钥的持有人–银行才能对你的消息解密。与对称加密不同的是,银行不需要将私钥通过网络发送出去,因此安全性大大提高。
总结
所以基本上都是先用非对称加密传输对称加密的秘钥。
HTTP请求
HTTP请求得到资源文件,如果有gzip压缩的话还需要解压,然后是一些HTTP小的零碎知识点。
HTTP报文
HTTP 报文是由 请求报文+响应报文 共同组成
- 请求报文:
- 定义:所有经过传输协议,客户端传递给服务器的内容,都被成为请求报文
- 包含:
- 起始行
- 请求头(请求首部)
- 请求主体
- 响应报文:
- 定义:所有经过传输协议,服务器返回给客户端的内容,都被成为响应报文
- 包含:
- HTTP状态码
- 响应头
- 响应主体
HTTP状态码
1~5开头,三位数字
- 1 开头的代表处理中,一般见不到
- 2开头:都是成功
- 200:OK:成功
- 201:CREATED:一般应用于告诉服务器创建一个新文件,最后服务器创建成功后返回的状态码
- 204:NO CONTENT:对于某些请求(例如:PUT或者DELETE),服务器不想处理,可以返回空内容,并且用204状态码告知
- 3开头:代表成功,只不过中间需要中转一下
- 301:Moved Permanently:永久重定向(永久转移)
- 302:Moved Temporarily:临时转移,很早以前基本上用302来做,但是现在主要用307来处理这个事情,
- 307的意思就是临时重定向Temporary Redirect =>主要用于:服务器的负载均衡等
- 304:Not Modified:设置HTTP的协商缓存
- 4开头:都是失败
- 400:Bad Request:传递给服务器的参数错误
- 401:Unauthorized:无权限访问
- 404:Not Found:请求地址错误
- 5开头:都是失败
- 500:Internal Server Error:未知服务器错误
- 503:Service Unavailable:服务器超负荷
HTTP请求方式
其实正常会说到什么POST
, GET
之类的,但是我这里想说一下cors里面的东西。
还是本着既然学到这里顺路搞搞清楚
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
简单请求
只要同时满足以下两大条件,就属于简单请求。
(1) 请求方法是以下三种方法之一:
- HEAD
- GET
- POST
(2)HTTP的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值
application/x-www-form-urlencoded
、multipart/form-data
、text/plain
非简单请求
凡是不同时满足上面两个条件,就属于非简单请求。
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT
或DELETE
,或者Content-Type
字段的类型是application/json
。
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest
请求,否则就报错。
也就是我们常说的跨域,这个问题可以交由后端的同学设置白名单或者运维的同学设置。
如果是前端的同学做这种跨域的问题的话不太方便
比如
但是基本上我们常用的就是JSONP
具体这些方法和场景有机会的话具体说一下。
断开TCP连接
也就是之前的四次挥手,可以看一下上面的说的四次挥手
浏览器渲染页面
文件解码成功后会正式开始渲染流程,先会根据 HTML 构建 DOM 树,有 CSS 的话会去构建 CSSOM 树。如果遇到 script 标签的话,会判断是否存在 async 或者 defer ,前者会并行进行下载并执行 JS,后者会先下载文件,然后等待 HTML 解析完成后顺序执行。
如果以上都没有,就会阻塞住渲染流程直到 JS 执行完毕。遇到文件下载的会去下载文件,这里如果使用 HTTP/2 协议的话会极大的提高多图的下载效率。
CSSOM 树和 DOM 树构建完成后会开始生成 Render 树,这一步就是确定页面元素的布局、样式等等诸多方面的东西
在生成 Render 树的过程中,浏览器就开始调用 GPU 绘制,合成图层,将内容显示在屏幕上了。
总结
- URL解析
- DNS解析
- 建立连接
- 如果有加密的话要先解密
- 然后http请求获取资源
- 断开连接
- 得到资源之后如果有gzip压缩要先解压
- 然后先构建DOM树,CSS树。下载JS文件,然后下载图片。然后生成Render树,最后确定布局,GPU绘制。
索引
https://www.ruanyifeng.com/blog/2016/04/cors.html
前端面试之道(掘金小册