简单来说,共有以下几个过程
- URL解析
- 判断缓存
- DNS解析:将域名解析成ip地址
- TCP的连接:TCP的三次握手
- 发送http请求
- 服务器处理请求并返回http报文
- 游览器解析渲染页面
- 断开连接:http的第四次挥手
URL 中文名:统一资源定位系统
定义:因特网的万维网服务程序上用于指定信息位置的表示方法
语法:协议+端口或IP+域名+端口号+路径+查询字符串+锚点等7部分组成(端口或IP与域名是映射关系)
举例:www.baidu.com/s?wd=hello&…
一、解析URL:首先会对 URL 进行解析,分析所需要使用的传输协议和请求的资源的路径。
二、缓存判断: 浏览器会判断所请求的资源是否在缓存里
可以看看我对强缓存和协商缓存的另一篇HTTP缓存有哪些方案
三、DNS解析
当游览器输入网址后,首先要经过域名解析,游览器要向这个URL/网址的主机名对应的服务器发送请求,获取服务器的IP;对于游览器来说,DNS的作用就是将主机名/URL转换成服务器的IP。
- ip
网络之间互联的协议
用来定位一个设备;封装数据报文,跟其他设备交流。
- 域名解析
DNS 是一个应用层协议提供通过域名查找 IP 地址,或逆向从 IP 地址反查域名的服务。
DNS 是一个网络服务器,我们的域名解析简单来说就是在 DNS 上记录一条信息记录。
- 浏览器如何通过域名去查询 URL 对应的 IP 呢?
DNS域名解析分为递归查询和迭代查询两种方式,现一般为迭代查询。
- 递归查询
我们的浏览器、操作系统、路由器都会缓存一些URL对应的IP地址,统称为DNS高速缓存。
这是为了加快DNS解析速度,使得不必每次都到根域名服务器中去查询。
- 迭代查询
局部的DNS服务器并不会自己向其他服务器进行查询,而是把能解析该域名的服务器IP地址返回给客户端。
客户端会不断的向其他服务器进行查询,直达查询到了。
迭代的话只会帮你找到相关的服务器,然后说我现在比较忙,你去其他地找吧。
- DNS负载均衡
作用:现在很多网站都会有多个服务器,当网站访问量过大的时候,如果请求都在同一个服务器的时候,服务器就会挂掉。
这个时候DNS负载均衡技术就起到作用,网站有多个服务器的时候,
在响应DNS的时候,DNS服务器会对每个查询返回不同的解析结果,
也就是返回不同的IP地址,从而把访问引导不同的服务器上,来达到负债均衡的目的。
- DNS预解析
DNS Prefetch
当游览网站的时候,浏览器会在加载网页时对网页中的域名进行解析缓存,提前解析,减少页面卡顿
四、建立TCP连接时server与client的三次握手
- SYN(synchronous建立联机)
- ACK(acknowledgement 确认)
-
游览器向服务器发送TCP数据,
SYN连接请求报文段和一个随机序号:SYN(seq=x)请求发送后,客户端便进入 SYN-SENT 状态。
-
服务器向游览器发送TCP数据:
ACK(seq=x+1),SYN(Y)服务端接收到请求后如果同意连接,则会发送一个应答,向服务器端发送一个
SYNACK报文段,确认连接请求,并且也向客户端发送一个随机序号。
发送完成后便进入 SYN-RECEIVED 状态。 -
游览器向服务器发送TCP数据:
ACK(seq=y+1)客户端接收服务器的确认应答后,同时向服务器也发送一个ACK 确认报文段,客户端发完这个报文段后便进入 ESTABLISHED 状态,
服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接建立成功。
- 为什么需要三次握手,两次不行吗?
其实这是由TCP的自身特点可靠传输决定的。客户端和服务端要进行可靠传输,那么就需要确认双方的接收和发送能力。
第一次握手可以确认客服端的发送能力,
第二次握手,服务端SYN=1,Seq=Y就确认了发送能力,ACK=X+1就确认了接收能力,
第三次握手才可以确认客户端的接收能力。不然容易出现丢包的现象。
五、HTTP请求
六、服务器处理请求并返回 HTTP 报文
每台服务器上都会安装处理请求的应用——Web Server。常见的Web Server 产品有 apache、nginx、IIS 或 Lighttpd 等。
假设我是一个传统的MVC模型
HTTP请求一般可以分为两类,静态资源 和 动态资源。
请求访问静态资源,这个就直接根据url地址去服务器里找就好了。
请求动态资源的话,就需要web server把不同请求,委托给服务器上处理相应请求的程序进行处理(例如 CGI 脚本,JSP 脚本,servlets,ASP 脚本,服务器端 JavaScript,或者一些其它的服务器端技术等),然后返回后台程序处理产生的结果作为响应,发送到客户端。
服务器在处理请求的时候主要有三种方式:
- 第一种:是用一个线程来处理所有的请求,并且同时只能处理一个请求,但是这样的话性能是非常的低的。
- 第二种:是每一个请求都给他分配一个线程但是当链接和请求比较多的时候就会导致服务器的cpu不堪重负。
- 第三种:就是采用复用I/O的方式来处理例如通过epoll方式监视所有链接当链接状态发生改变的时候才去分配空间进行处理。
七、浏览器渲染页面
浏览器首先会根据 html 文件(响应) 建 DOM 树,根据解析到的 css 文件构建 CSSOM 树,如果遇到 script 标签,则判端是否含有 defer 或者 async 属性,要不然 script 的加载和执行会造成页面的渲染的阻塞。
当 DOM 树和 CSSOM 树建立好后,根据它们来构建渲染树。渲染树构建好后,会根据渲染树来进行布局。布局完成后,最后使用浏览器的 UI 接口对页面进行绘制。这个时候整个页面就显示出来了。
八、断开连接:TCP 四次挥手
- ACK(acknowledgement 确认)
- FIN(finish结束)
-
游览器向服务器发送TCP数据:
FIN(seq=x),向服务端发送连接释放请求 -
服务器向游览器发送TCP数据:
ACK(seq=x+1)服务端收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时表明客户端到服务端的连接已经释放,不再接收客户端发的数据了。 但是因为 TCP 连接是双向的,所以服务端仍旧可以发送数据给客户端。
-
服务器向游览器发送TCP数据:
FIN(seq=y)服务端如果此时还有没发完的数据会继续发送,完毕后会向客户端发送连接释放请求,然后服务端便进入 LAST-ACK 状态。
-
游览器向服务器发送TCP数据:
ACK(seq=y+1)客户端收到释放请求后,向服务端发送确认应答,此时客户端进入 TIME-WAIT 状态。
该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有服务端的重发请求的话,就进入 CLOSED 状态。
当服务端收到确认应答后,也便进入 CLOSED 状态。
- 为啥2、3挥手分手不能合并
2、3挥中间服务器有可能还有数据要发送,不能提前发送FIN - 为啥游览器发送ACK之后不直接关闭,而是要等一阵子关闭?
当游览器收到服务端的连接释放报文后,对此发出确认问报段ACK(seq=y+1),游览器进行TIME_WAIT状态,此时TCP未释放,需要经过计时器设置等待的时间2MSL后,游览器才进入closed状态。
如果不等待,游览器直接关闭,当服务器还有数据包要传递给游览器,且还在路上的时候,游览器被新的端口占用,那就接收到了无用包,造成数据混乱
- 为啥TIME_WAIT状态需要设置时间2MSL,才能返回close状态?
理论上,四个报文都发送完毕,就可以直接进入CLOSE状态了,但是可能网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。 1 个 MSL 确保四次挥手中主动关闭方最后的 ACK 报文最终能达到对端; 1 个 MSL 确保对端没有收到 ACK 重传的 FIN 报文可以到达。