浏览器工作原理
流程
用户 URL 输入
URL(统一资源定位符,Uniform Resource Locator)用于定位互联网上资源,俗称网址。
老页面 beforeunload 事件
- 检查输入的内容是否是一个合法的 URL 链接。
- 是,则判断输入的 URL 是否完整。如果不完整,浏览器可能会对域进行猜测,补全前缀或者后缀。
- 否,将输入内容作为搜索条件,使用用户设置的默认搜索引擎来进行搜索。
大部分浏览器会从历史记录、书签等地方开始查找我们输入的网址,并给出智能提示。
首先,网络进程会查找本地缓存是否缓存了该资源。 如果有缓存资源,那么直接返回资源给浏览器进程; 如果在缓存中没有查找到资源,那么直接进入网络请求流程。
DNS(Domain Name System)解析
这请求前的第一步是要进行 DNS 解析,以获取请求域名的服务器 IP 地址。 如果请求协议是 HTTPS,那么还需要建立 TLS 连接。
其中,DNS 也有几步缓存:浏览器缓存,hosts 文件, 如果本地域名解析服务器也没有该域名的记录,则开始递归+迭代解析
因为浏览器不能直接通过域名找到对应的服务器 IP 地址,所以需要进行 DNS 解析,查找到对应的 IP 地址进行访问。 DNS 解析流程如下:
- 在浏览器中输入 hzfe.org 域名,操作系统检查浏览器缓存和本地的 hosts 文件中,是否有这个网址记录,有则从记录里面找到对应的 IP 地址,完成域名解析。
- 查找本地 DNS 解析器缓存中,是否有这个网址记录,有则从记录里面找到对应的 IP 地址,完成域名解析。
- 使用 TCP/IP 参数中设置的 DNS 服务器进行查询。如果要查询的域名包含在本地配置区域资源中,则返回解析结果,完成域名解析。
- 检查本地 DNS 服务器是否缓存该网址记录,有则返回解析结果,完成域名解析。
- 本地 DNS 服务器发送查询报文至根 DNS 服务器,根 DNS 服务器收到请求后,用顶级域 DNS 服务器地址进行响应。
- 本地 DNS 服务器发送查询报文至顶级域 DNS 服务器。顶级域 DNS 服务器收到请求后,用权威 DNS 服务器地址进行响应。
- 本地 DNS 服务器发送查询报文至权威 DNS 服务器,权威 DNS 服务器收到请求后,用 hzfe.org 的 IP 地址进行响应,完成域名解析。 查询通常遵循以上流程,从请求主机到本地 DNS 服务器的查询是递归查询,DNS 服务器获取到所需映射的查询过程是迭代查询。
3. 建立 TCP 连接#
三次握手
世界上几乎所有的 HTTP 通信都是由 TCP/IP 承载的,TCP/IP 是全球计算机及网络设备都在使用的一种常用的分组交换网络分层。 HTTP 的连接实际上就是 TCP 连接以及其使用规则。 –《HTTP 权威指南》
当浏览器获取到服务器的 IP 地址后,浏览器会用一个随机的端口(1024 < 端口 < 65535)向服务器 80 端口发起 TCP 连接请求(注:HTTP 默认约定 80 端口,HTTPS 为 443 端口)。这个连接请求到达服务端后,通过 TCP 三次握手,建立 TCP 的连接。
3.1 分层模型#
---------------------------------- 7| 应用层 | | HTTP | 6| 表示层 | 应用层 | 5| 会话层 | | | --------------------------------- 4| 传输层 | 传输层 | TCP TLS | --------------------------------- 3| 网络层 | 网络层 | IP | --------------------------------- 2| 数据链路层 | 链路层 1| 物理层 -------------------------------- [OSI] | [TCP/IP]
Copy
3.2 TCP 三次握手#
SYN 是建立连接时的握手信号,TCP 中发送第一个 SYN 包的为客户端,接收的为服务端# TCP 中,当发送端数据到达接收端时,接收端返回一个已收到消息的通知。这个消息叫做确认应答 ACK 假设有客户端 A,服务端 B。我们要建立可靠的数据传输。 SYN(=j) // SYN: A 请求建立连接 A ----------> B | ACK(=j+1) | // ACK: B 确认应答 A 的 SYN SYN(=k) | // SYN: B 发送一个 SYN A <----------- | | ACK(=k+1) -----------> B // ACK: A 确认应答 B 的包
Copy
- 客户端发送 SYN 包(seq = j)到服务器,并进入 SYN_SEND 状态,等待服务器确认。
- 服务器收到 SYN 包,必须确认客户的 SYN(ACK = k + 1),同时自己也发送一个 SYN 包(seq = k),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态。
- 客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK(ACK = k + 1),此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手。
4. TLS 协商#
建立连接后就可以通过 HTTP 进行数据传输。如果使用 HTTPS,会在 TCP 与 HTTP 之间多添加一层协议做加密及认证的服务。HTTPS 使用 SSL(Secure Socket Layer) 和 TLS(Transport Layer Security) 协议,保障了信息的安全。
-
SSL
-
认证用户和服务器,确保数据发送到正确的客户端和服务器。
-
加密数据防止数据中途被窃取。
-
维护数据的完整性,确保数据在传输过程中不被改变。
-
TLS
-
用于在两个通信应用程序之间提供保密性和数据完整性。该协议由两层组成:TLS 记录协议(TLS Record)和 TLS 握手协议(TLS Handshake)。较低的层为 TLS 记录协议,位于某个可靠的传输协议(例如 TCP)上面。
4.1 TLS 握手协议#
- 客户端发出一个 client hello 消息,携带的信息包括:所支持的 SSL/TLS 版本列表;支持的与加密算法;所支持的数据压缩方法;随机数 A。
- 服务端响应一个 server hello 消息,携带的信息包括:协商采用的 SSL/TLS 版本号;会话 ID;随机数 B;服务端数字证书 serverCA;由于双向认证需求,服务端需要对客户端进行认证,会同时发送一个 client certificate request,表示请求客户端的证书。
- 客户端校验服务端的数字证书;校验通过之后发送随机数 C,该随机数称为 pre-master-key,使用数字证书中的公钥加密后发出;由于服务端发起了 client certificate request,客户端使用私钥加密一个随机数 clientRandom 随客户端的证书 clientCA 一并发出。
- 服务端校验客户端的证书,并成功将客户端加密的随机数 clientRandom 解密;根据随机数 A/随机数 B/随机数 C(pre-master-key) 产生动态密钥 master-key,加密一个 finish 消息发至客户端。
- 客户端根据同样的随机数和算法生成 master-key,加密一个 finish 消息发送至服务端。
- 服务端和客户端分别解密成功,至此握手完成,之后的数据包均采用 master-key 进行加密传输。
5. 服务器响应#
连接建立之后,浏览器端会构建请求行、请求头等信息,并把和该域名相关的 Cookie 等数据附加到请求头中,然后向服务器发送构建的请求信息。 数据在进入服务端之前,可能还会先经过负责负载均衡的服务器,它的作用就是将请求合理的分发到多台服务器上,这时假设服务端会响应一个 HTML 文件。
首先浏览器会判断状态码是什么,如果是 200 那就继续解析,如果 400 或 500 的话就会报错,如果 300 的话会进行重定向,这里会有个重定向计数器,避免过多次的重定向,超过次数也会报错。 浏览器开始解析文件,如果是 gzip 格式的话会先解压一下,然后通过文件的编码格式知道该如何去解码文件。
当浏览器到 web 服务器的连接建立后,浏览器会发送一个初始的 HTTP GET 请求,请求目标通常是一个 HTML 文件。服务器收到请求后,将发回一个 HTTP 响应报文,内容包括相关响应头和 HTML 正文。
<html>
<head>
<meta charset="UTF-8" />
<title>我的博客</title>
<link rel="stylesheet" src="styles.css" />
<script src="index.js"></script>
</head>
<body>
<h1 class="heading">首页</h1>
<p>A paragraph with a <a href="https://hzfe.org/">link</a></p>
<script src="index.js"></script>
</body>
</html>