文章目录
一、将域名www.baidu.com解析为IP地址
解析IP地址的过程依次经过了:浏览器缓存、系统缓存、hosts文件、路由器缓存、递归搜索根域名服务器。
-
浏览器缓存: 每个浏览器都会有一个DNS缓存,记录了一些常用域名和IP地址的对应关系(有过期时间),当在浏览器的DNS缓存中没有找到对应关系时,会查询系统缓存
-
系统缓存: 浏览器会进行一个系统调用(Windows里面是gethostbyname),检查本机的
C:\Windows\System32\drivers\etc\hosts
配置文件下有没有这个域名的映射。有,直接返回对应的IP地址;没有的话就去查询路由器缓存。 -
路由器缓存: 查询路由器的DNS缓存,没有就去查本地DNS服务器
-
递归搜索DNS服务器:
-
系统会把浏览器的解析请求发送到本地DNS服务器,如果缓存中有对应的解析记录,就会直接返回IP地址;没有的话本地 DNS 服务器还要向 DNS 根服务器进行查询。
-
本地 DNS 服务器向根服务器发送 DNS 请求,如果根服务器经过查询,没有记录该域名及 IP 地址的对应关系,就会告诉本地 DNS 服务器,可以到域名服务器上继续查询,并给出域名服务器的地址(.com 服务器)。
-
本地 DNS 服务器向 .com 服务器发送 DNS 请求,.com 服务器收到请求后,不会直接返回域名和 IP 地址的对应关系,而是告诉本地 DNS 服务器,该域名可以在 baidu.com 域名服务器上进行解析获取 IP 地址,并告诉 baidu.com 域名服务器的地址。
-
本地 DNS 服务器向 baidu.com 域名服务器发送 DNS 请求,baidu.com 服务器收到请求后,在自己的缓存表中发现了该域名和 IP 地址的对应关系,并将IP地址返回给本地 DNS 服务器。
-
本地 DNS 服务器将获取到与域名对应的 IP 地址返回给客户端,并且将域名和 IP 地址的对应关系保存在缓存中,以备下次别的用户查询时使用
二、三次握手建立TCP/IP连接
假设 A 为客户端,B 为服务器端:
- 首先 B 处于 LISTEN(监听)状态,等待客户的连接请求
- A 向 B 发送连接请求报文,SYN=1,ACK=0,选择一个初始的序号 x
- B 收到连接请求报文,如果同意建立连接,则向 A 发送连接确认报文,SYN=1,ACK=1,确认号为 x+1,同时也选择一个初始的序号y
- A 收到 B 的连接确认报文后,还要向 B 发出确认,确认号为 y+1,序号为 x+1
- B 收到 A 的确认后,连接建立
三、浏览器根据解析得到的IP地址向 web 服务器发送一个 HTTP 请求
像baidu主页这样的动态页面,打开后在浏览器缓存中很快甚至马上就会过期,毫无疑问他们不能从中读取。所以,浏览器将把请求发送到baidu主页所在的服务器:
GET https://www.baidu.com/ HTTPS/1.1
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36 // User-Agent:发送请求的应用程序名称
Accept-Encoding: gzip, deflate, br //指定可接收的数据压缩格式
Accept-Language: zh-CN,zh;q=0.9 //指定可以接收的语言
Connection: keep-alive
Host: www.baidu.com //接收请求的服务器地址,可以是ip也可以是端口号
Cookie: datr=1265876274-[...]; locale=en_US; lsd=WW[...]; c_user=2101[...]
GET 这个请求定义了要读取的URL: https://baidu.com/
。 浏览器自身定义 (User-Agent 头), 和它希望接受什么类型的相应 (Accept and Accept-Encoding 头)。 Connection头keep-alive要求服务器为了后边的请求不要关闭TCP连接。
请求中也包含浏览器存储的该域名的cookies。可能你已经知道,在不同页面请求当中,cookies是与跟踪一个网站状态相匹配的键值。这样cookies会存储登录用户名,服务器分配的密码和一些用户设置等。Cookies会以文本文档形式存储在客户机里,每次请求时发送给服务器,以识别客户端身份
用来看原始HTTP请求及其相应的工具很多,例如:fiddler、FireBug等工具,这些软件在网站优化时会帮上很大忙。除了获取请求,还有一种是发送请求,它常在提交表单用到。发送请求通过URL传递其参数(例如:http://robozzle.com/puzzle.aspx?id=85),发送请求在请求正文头之后发送其参数
像https://baidu.com/
中的斜杠是至关重要的。这种情况下,浏览器能安全的添加斜杠。而像http://example.com/folderOrFile
这样的地址,因为浏览器不清楚folderOrFile到底是文件夹还是文件,所以不能自动添加斜杠。这时,浏览器就不加斜杠直接访问地址,服务器会响应一个重定向,结果造成一次不必要的握手
四、经路由器转发,将HTTP请求送达服务器
首先在应用层,根据当前的需求和动作,结合应用层的协议和确定发送的数据内容,我们把这些数据放到一个缓冲区内,然后形成了应用层的报文data
这些数据通过传输层发送(HTTP请求采用tcp协议),在这里报文打上了传输头的报头,主要包含端口号,以及tcp的各种制信息,这些信息是直接得到的,因为接口中需要指定端口,这样就组成了tcp的数据传送单位segment
然后待发送的数据段送到网络层,在网络层被打包,这样封装上了网络层的报头,报头内部含有源及目的ip地址,该层数据发送单位被称为packet。网络层开始负责将这样的数据包在网络上传输,如何穿过路由器,最终到达目的地址。在这里,根据目的ip地址,就需要查找下一跳路由的地址。首先在本机,要查找本机的路由表,在windows上运行route print
就可以看到当前路由表内容,有如下几项:
- Active Routes
- Default Route
- Persistent Route
整个查找过程如下:
-
根据目的地址,通过子网掩码计算目的网段,如果处在同一个内网,则可以直接发送
-
如果不是,则查询路由表,找到一个路由
-
如果找不到明确的路由,此时在路由表中还会有默认网关Gateway,也可称为缺省网关,IP用缺省的网关地址将一个数据传送给下一个指定的路由器,所以网关也可能是路由器,也可能只是内网向特定路由器传输数据的网关。
-
路由器收到数据后,它再次为远程主机或网络查询路由,若还未找到路由,该数据包将发送到该路由器的缺省网关地址。而数据包中包含一个最大路由跳数,如果超过这个跳数,就会丢弃数据包,这样可以防止无限传递。路由器收到数据包后,只会查看网络层的包裹数据,目的ip。所以说它是工作在网络层,传输层的数据对它来说则是不可见的
如果上面这些步骤都没有成功,那么该数据报就不能被传送。如果不能传送的数据报来自本机,那么一般会向生成数据报的应用程序返回一个“主机不可达”或 “网络不可达”的错误
五、服务器处理HTTP请求,并返回HTML文件
1. 接收http请求
web服务器链接表中有许多链接需求要被处理,处理的方式包括单线程和多线程等,一旦web服务器端接收到某条链路的请求就会将其加入相应的等待请求队列,等候处理。
2. 处理http请求
将http请求的信息解析出来的大致过程如下:
3. 访问资源
如果访问静态资源,则直接根据url地址去服务器里面找
如果访问动态资源,则需要先经过cgi,再用服务器脚本处理,最后返回给前端
3. 构建响应
找到资源:构建响应信息,包括响应的对象类型、长度、状态码等。
未找到资源:构建重定向响应,直接返回重定向,客户端收到响应后再向重定向地址发送请求,重定向的响应状态码一般是3xx
六、浏览器解析HTML文件,并显示
浏览器是按顺序解析html文档的,但是浏览器解析html文档的第一步,是并行发出请求来请求所有的外部资源。然后再从头开始解析,如果有js等外部资源还没有加载则需要等待。
浏览器解析HTML的流程:
- 解析HTML结构
- 并行加载脚本、样式表文件、img等外部资源
- 如有js文件未下载,则等待下载完成(js文件前如有css文件,则需要先等css文件下载完成)
- 脚本下载后立即执行,然后从当前解析处开始解析
- DOM树构建完成。//DOMContentLoaded
- 解析外部css文件,img图片等资源
- paint,渲染页面
- 页面加载完毕。//load
开始从头到尾解析HTML,并生成DOM树。其中如果有外链资源,需要再次通过网络层以此下载。如果是"script"标签,则需要调用JS引擎执行脚本;如果是css,则开始解析CSS,得到一系列样式规则;DOM树生成之后,与样式规则拼接,得到渲染树。渲染树经过排版引擎得到最终的渲染位置和样式,然后调用操作系统的绘图API绘制页面(部分内容会调用显卡进行硬件加速)
七、总结
1. 浏览器在拿到 url 时,首先会对 url 进行解析,将域名与实际的文件路径分离,然后需要使用 DNS 协议,通过域名得到 IP 地址
-
浏览器会查询浏览器缓存,如果有这个网址的缓存就可以直接获取到 IP,如果没有就进一步访问本机缓存,如果本机缓存也没有才会发起 DNS 请求。
-
而 DNS 的服务器是一个树状结构,对于域名来说是倒着进行解析的,根节点是根 DNS 服务器,他的子节点为 com、cn 这种顶级域 dns 服务器,然后进一步向下进行解析。
-
以 baidu.com 为例,当我们的电脑需要发起 DNS 请求的时候,会先对根 DNS 服务器发起请求,这个服务器的 IP 地址一般在每台电脑上都有,我们一般会设置为 8.8.8.8 或者 114.114.114.114,我们的电脑在访问根 DNS 服务器后,会得到 con 域 DNS 服务器的 IP,然后会继续访问 con 域 DNS 服务器,这时就能得到 baicu.com 的 IP 地址了
2. 得到 ip 地址后,浏览器会先与服务器通过 TCP 三次握手建立连接,然后构建 HTTP 请求
HTTP协议是一种基于TCP/IP的应用层协议,进行HTTP数据请求必须先建立TCP/IP连接
可以这样理解:HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。两个计算机之间的交流无非是两个端口之间的数据通信,具体的数据会以什么样的形式展现是以不同的应用层协议来定义的
3. 构建HTTP请求,使用TCP协议发送
通过 DNS 请求获取到 ip 后,浏览器会构建并发送 HTTP 请求或者 HTTPS 请求,HTTPS 就是在 HTTP 的基础上加了一个 TLS 协议来进行数据加密。HTTP 请求发出后会将数据包交给下层协议栈处理,在传输层和网络层该数据包会被分别加上 TCP 头和 IP 头,并且被发送出去,沿路的网关会收到这个数据包并进行识别和转发,直到该数据包被服务器收到,通过相同的流程返回回复数据包
4. 服务器解析请求,并返回响应
服务端在解析 url 时,我们能获取到需要请求资源的资源路径、端口号、请求参数等信息,这些信息会被存储在 http 头中。服务端通过解析http请求中的相关信息,访问相应的资源(静态资源或动态资源),并生成相应的HTML文件发送给浏览器