输入一个 URL 到页面展现出来,整个过程发生了什么?我们先讲讲大概,然后再做进一步解析。大致的过程如下:
- DNS 域名解析:将 URL 解析成 IP 地址
- TCP 连接:浏览器与服务器通过三次握手建立 TCP 连接
- 发送 HTTP 请求:浏览器以报文形式向服务器发送请求
- 查找返回:服务器接受请求并查找资源返回 HTTP 响应
- 渲染页面:浏览器接收资源渲染页面
一、DNS域名解析
先说说 URL(即从浏览器输入的网址),URL 是统一资源定位符,用于搜索互联网或者本地资源。包括协议、域名、端口号。例如 https://www.github.com:8080,其中采用的是 https 协议,域名是 www.github.com,后面跟个冒号加数字则是端口号。
而域名解析就是通过 DNS 找到 www.github.com 这串域名其对应的 IP。因为浏览器实际上并不认识 www.github.com 这串是什么,所以要先查找这个网站所在的服务器 IP,再通过 IP 找到对应的服务器连接。域名解析的过程大概如下:
- 浏览器缓存:因为浏览器会缓存 DNS 记录一段时间,所以会先从浏览器缓存的 DNS 中寻找是否有 www.github.com 所对应的 IP。
- 系统缓存:寻找系统的 hosts 文件,看是否有对应的域名和 IP。
- 路由缓存:一般路由器也会缓存域名和 IP 信息。
- ISP DNS缓存:如果在路由器缓存中找不到,则接着去找 ISP 的 DNS 缓存服务器。(ISP 即运营商,如电信移动联通等,在我们的网络配置中有一项 DNS 服务地址配置,浏览器会将域名信息发给此处指定的 DNS 去查找,114.114.114.114是国内的通用 DNS 服务器,而8.8.8.8是谷歌的 DNS 服务器)。
- 根域迭代查询:如果上述都查找不到,则本地 DNS 将域名发给互联网的根域。
- 根域把域名中的顶级域(即 www.github.com 中的
com)的服务器 IP 地址返回给本地 DNS。 - 本地 DNS 根据返回的顶级域的服务器 IP 发起请求,继续查找二级域名(github.com)的服务器 IP 地址返回。
- 然后本地再向二级域发送请求一直迭代查询下去,直到得到最终的 IP 结果返回给主机。
二、浏览器与服务器建立TCP连接
拿到域名对应的IP之后,浏览器和服务器之间需要通过三次握手建立 TCP 连接。
- 第一次握手:建立连接时,客户端发送 SYN 包(
syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认。SYN:同步序列编号(Synchronize Sequence Numbers)。 - 第二次握手:服务器收到 SYN 包,必须确认客户的 SYN(
ack=j+1),同时自己也发送一个 SYN 包(syn=k),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态。 - 第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK(
ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED(TCP连接成功)状态,完成三次握手。
简单概括下三次握手:
- 第一次浏览器向服务器发起连接请求然后等待回应。
(浏览器:有空?可以发东西?) - 第二次服务器收到请求然后返回信息告知浏览器你可以发东西给我了并进入等待状态。
(服务器:还需要吗?刚看到,可以发) - 第三次浏览器收到返回信息确认是自己发的连接请求然后连接成功。
(浏览器:还需要,那我发了)
三次握手
为什么不是两次握手?原因是防止已失效的连接请求报文段,突然又传送到了服务端而产生错误。(即一个小时前浏览器发的请求,服务器突然收到了,然后就一直在等待连接,可此时浏览器已经过了一小时前的发送需求了。)所以需要浏览器才发一次确认包,表达自己当前确实有发送需求才真正进入连接。
三、浏览器向服务器发送HTTP请求
建立 TCP 连接之后,浏览器会以一个随机端口(1024<端口<65535)向 web 服务器发起一个 HTTP 请求。请求以报文的形式发送,一个完整的报文包含以下三个部分:报文首部、空行、报文正文。
请求报文
GET https://github.com/luoshaoxiong/fe_handbook/issues/25 HTTP/2.0
Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Host:github.com
Pragma:no-cache
Referer:https://github.com/luoshaoxiong/fe_handbook/issues/25
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36
X-Requested-With:XMLHttpRequest
四、服务器查找返回资源
服务器是一台安装了处理请求的应用( Web server )的机器,常见的 Web server 有 Apache、Nginx、IIS、Lighttpd 。web 服务器接受用户的请求后,会交给对应的网站代码去处理或者反向代理到其他服务器。
服务器处理
如图,假设有两个网址:https://github.com/luoshaoxiong/ 和 https://luoshaoxiong.github.io/,经 DNS 域名解析之后指向同一台 IP 服务器,当请求发到该服务器上后,会交给 nginx 处理,在 nginx 里有个配置文件,会控制对应的网址去访问服务器不同文件下下的网站代码,如 https://github.com/luoshaoxiong/ 最后交给 var/www/github 去处理,https://luoshaoxiong.github.io/ 交给 var/www/io 去处理。
而后端拿到客户端发来的数据后,处理流程如下图。一般都采用 MVC 模式,M 即 Model(模型),V 即 View(视图),C 即 Controller(控制器)。
MVC处理流程
- 将请求的 path 交给路由去匹配。
- 路由匹配到之后交给对应的控制器去处理。
- 控制器一般不直接操作数据库,而是通过模型去读取操作数据库。
- 数据库将读取到的数据返回给模型。
- 模型将数据再返回给控制器。
- 控制器将处理好的数据交给视图去处理,视图会将数据和 html 组合形成最后的页面代码。
- 视图将填充好数据的页面代码返回控制器。
- 控制器再将页面返回给客户端。
五、浏览器渲染页面
接收到服务器返回的 html 文件之后,浏览器会从上到下一句一句读取执行 html,解析步骤大致如下(此处以 webkit 内核浏览器为例):
- 解析 DOM 标签,生成 DOM 树。
- 解析 CSS 标签,生成 CSS 树。
- 将 DOM 树和 CSS 树结合生成 render 树。
- 在渲染树的基础上进行布局,计算每个节点的几何结构,如位置大小等。
- 将每个节点绘制到页面上。
浏览器解析
浏览器渲染其实也是个很重要的大话题,此处我们不做过多展开,下篇再做详细介绍。
六、断开连接(四次挥手)
实际上从 URL 到页面展示主要就上面的 5 步,因为现在的 HTTP 已经支持持久连接了,建立 TCP 连接后就可以一直发送 HTTP 请求,不需要再断开连接再重新连接那么麻烦了。但还是觉得断开连接有必要了解下,所以此处也写下。
当断开 TCP 连接时,需要通过四次挥手来实现。即终止 TCP 连接,需要客户端和服务端总共发送4个包确认连接的断开。过程如下:
四次挥手
- 第一次挥手:客户端发送一个 FIN,用来关闭客户端到服务端的数据传送,然后进入FIN_WAIT_1状态。
- 第二次挥手:服务端收到 FIN 后,发送一个 ACK 给客户端,值为收到的 FIN 加 1,服务端进入 CLOSE_WAIT 状态。
- 第三次挥手:服务端发送一个 FIN,用来关闭服务端到客户端的数据传送,然后进入LAST_ACK状态。
- 第四次挥手:客户端收到 FIN 后,进入 TIME_WAIT 状态,接着发送一个 ACK 给服务端,值为服务端发来的 FIN 加 1,服务端进入 CLOSED 状态,完成四次挥手。
- 客户端:我准备关了!
- 服务端:收到!不过我还在发,等会就关。
- 服务端:我也可以关了!
- 客户端:收到!我这边关好了,你放心关吧。
4)为什么建立连接是三次握手,而关闭连接却是四次挥手呢?
这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。
参考文章:
https://segmentfault.com/a/1190000003925803
http://web.jobbole.com/91239/
https://www.jianshu.com/p/d616d887953a
https://juejin.im/entry/58f867045c497d0058e2ff3a
https://segmentfault.com/a/1190000009317496
关于三次握手与四次挥手面试官想考我们什么?--- 不看后悔系列
https://zhuanlan.zhihu.com/p/57895541
https://blog.csdn.net/yu876876/article/details/81560122
https://www.jianshu.com/p/fc957e25102e
https://segmentfault.com/a/1190000003925803
https://segmentfault.com/a/1190000006879700











网友评论