一、大致流程
●URL解析
●DNS解析(将输入的域名解析成IP地址)
●建立TCP连接(TCP三次握手)
●发送HTTP请求
●服务器处理请求并响应 HTTP 报文
●浏览器接受响应
●渲染页面
●断开连接(TCP 四次挥手)
二、URL 解析
2.1 URL 介绍
URL(Uniform Resource Locator),统一资源定位符,用于定位互联网上资源,俗称网址。比如 www.w3school.com.cn/html/index.…,
遵守以下的语法规则:scheme://host.domain:port/path/filename,各部分名次解释如下:
●scheme - 定义因特网服务的类型。常见的协议有 http、https、ftp、file,其中最常见的类型是 http,而 https 则是进行加密的网络传输。
●host - 定义域主机(http 的默认主机是 www)
●domain - 定义因特网域名,比如 w3school.com.cn
●port - 定义主机上的端口号(http 的默认端口号是 80)
●path - 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。
●filename - 定义文档/资源的名称
2.2 URL解析流程
●地址解析
首先会判断输入的是否是一个合法的URL,还是一个待搜索关键字,所以就需要根据输入的内容进行自动完成,字符编码等操作,一个合法的URL,一定包含协议、域名等信息。
●HSTS
由于安全隐患,会使用 HSTS 强制客户端使用 HTTPS 访问页面。
●其他操作
浏览器还会进行一些额外的操作,比如安全检查、访问限制(之前国产浏览器限制 996.icu)。
●检查缓存
三、 DNS解析
3.1 IP地址
IP 地址是指互联网协议地址,是 IP Address 的缩写,IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一台主机和每一个网络分配一个逻辑地址,以此来屏蔽与物理地址的差异。IP地址是一个32位的二进制书,比如本机的IP地址: 127.0.0.1,
3.2 DNS 的概念
ip地址要么是纯数字,要么就是数字加字母(ipv4:104.17.208.102, ipv6: 2060:4700::6811:d166 ),记忆起来实在太难了,于是将ip地址和域名关联起来(www.example.com),在浏览器都是通过输入域名来得到相应的网页内容的,而不是IP地址,但是计算机智能识别并用IP地址定位,于是就需要域名解析道ip地址这个过程。 DNS通过域名查找IP地址,或者逆向从IP地址反查域名的服务。DNS 是一个网络服务器,我们的域名解析简单来说就是在DNS上记录一条信息记录。
3.3 域名结构树
域名结构树最顶部都是由一个点表示的,也就是说域名最终都会汇集到一个根管理,这个根是由13个根域名服务器组成的,这13个根域名服务器是由12个独立运营结构运营的。
服务器之间的关系:
根域名服务器会管理,com、cn、net等这个顶级域名服务器, 顶级域名服务器分别管理各自的权威域名服务器,权威域名服务器对应管理各自的主机。
3.4 DNS 解析过程
●浏览器缓存
浏览器需要看自己的浏览器缓存中有没有对应的ip记录。
●操作系统缓存
如果浏览器缓存中找不到需要的 DNS 记录,那就去操作系统中找。操作系统也有自己的 DNS缓存,但在这之前,会向检查域名是否存在本地的 Hosts 文件里,没有则向 DNS 服务器发送查询请求。
●路由器缓存
路由器也有自己的缓存。
●ISP DNS缓存
ISP 是互联网服务提供商(Internet Service Provider)的简称,ISP 有专门的 DNS 服务器应对 DNS 查询请求。ISP DNS 就是在客户端电脑上设置的首选 DNS 服务器,它们在大多数情况下都会有缓存。
●根DNS 服务器查询
ISP 的 DNS 服务器还找不到的话,它就会向根服务器发出请求,进行递归查询(DNS 服务器先问根域名服务器.com 域名服务器的 IP 地址,然后再问.bliliblili 域名服务器,依次类推)在前面所有步骤没有缓存的情况下,本地 DNS 服务器会将请求转发到互联网上的根域,下面这个图很好的诠释了整个流程:
注意:
解析器与本地dns服务器之间用的是递归的方式传输,传输以后回归,意思就是一路查下去中间不返回,得到最终结果才返回信息。而本地服务器与三层服务器之间用的是迭代的方式传输,第一步得到什么然后在用第二步。
四、建立连接
在客户端发送数据之前需要发起 TCP 三次握手建立与服务端的连接,用以同步客户端和服务端的序列号和确认号,并交换 TCP 窗口大小信息。所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。
4.1 Tcp 三次握手
(1) 第一次握手:建立连接时,客户端A发送SYN包(SYN=1,同时选择一个初始序列号 seq=x )到服务器B,并进入SYN_SEND状态,等待服务器B确认。
(2) 第二次握手:服务器B收到SYN包,必须确认客户A的SYN=1,同时自己也发送一个SYN包(SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号 seq=y),即SYN+ACK包,此时服务器B进入SYN_RECV状态。
(3) 第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ack=y+1,自己的序列号seq=Z),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成。
五、发送HTTP请求
TCP 三次握手结束后,浏览器和服务器就建立了连接,浏览器就会发送 HTTP 请求报文给服务器。请求报文由请求行、请求头、空行和请求数据组成,如下图所示:
●请求行内容
请求方法:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。
URL 请求地址: <协议>://<主机>:<端口>/<路径>?<参数> 组成
协议版本: http 版本号
例如: POST /chapter17/user.html HTTP/1.1
●请求头内容
请求的附加信息: 由键值对组成,每行一对,关键字和值用英文冒号“:”分隔;知道遇到了空行就意味着下面没有请求头部了,
请求头部通知服务器有关于客户端请求的信息。它包含许多有关的客户端环境和请求正文的有用信息。其中比如:Host,表示主机名,虚拟主机;Connection,HTTP/1.1 增加的,使用 keepalive,即持久连接,一个连接可以发多个请求;User-Agent,请求发出者,兼容性以及定制化需求。
●请求体: 承载多个请求参数的数据,包含回车符、换行符和请求数据,并不是所有请求都具有请求数据。
六、服务器处理请求并返回 HTTP 报文
响应流程大致如下:
http响应报文:
1.组成 : 响应行(request line)、响应头部(header)、响应主体三个部分组成。如下图所示:
(1) 响应行包含:协议版本,状态码,状态码描述
状态码规则如下:
1xx:指示信息--表示请求已接收,继续处理。
2xx:成功--表示请求已被成功接收、理解、接受。
3xx:重定向--要完成请求必须进行更进一步的操作。
4xx:客户端错误--请求有语法错误或请求无法实现。
5xx:服务器端错误--服务器未能实现合法的请求。
(2) 响应头部包含响应报文的附加信息,由 名/值 对组成
(3) 响应主体包含回车符、换行符和响应返回数据,并不是所有响应报文都有响应数据
七、浏览器解析渲染页面
浏览器拿到HTML,先将HTML转换成dom树,再将CSS样式转换成stylesheet,根据dom树和stylesheet创建布局树,对布局树进行分层,为每个图层生成绘制列表,再将图层分成图块,紧接着光栅化将图块转换成位图,最后合成绘制生成页面。
分层的目的: 避免整个页面渲染,把页面分成多个图层,尤其是动画的时候,把动画独立出一个图层,渲染时只渲染该图层就ok,transform,z-index等,浏览器会自动优化生成图层 光栅化目的:页面如果很长但是可视区很小,避免渲染非可视区的样式造成资源浪费,所以将每个图层又划分成多个小个子,当前只渲染可视区附近区域
八、断开连接
8.1 四次挥手
当数据传送完毕,需要断开 tcp 连接,此时发起 tcp 四次挥手。TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。
(1)客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送(报文段4)。发起方向被动方发送报文,Fin、Ack、Seq,表示已经没有数据传输了。并进入 FIN_WAIT_1 状态。(第一次挥手:由浏览器发起的,发送给服务器,我请求报文发送完了,你准备关闭吧)
(2)服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。被动方发送确认报文,Ack、Seq,表示同意关闭请求。此时主动发起方进入 FIN_WAIT_2 状态。(第二次挥手:由服务器发起的,告诉浏览器,我请求报文接受完了,我准备关闭了,你也准备吧)
(3)服务器B关闭与客户端A的连接,发送一个FIN给客户端A(报文段6)。被动方向发起方发送报文段,Fin、Ack、Seq,请求关闭连接。并进入 LAST_ACK 状态。(第三次挥手:由服务器发起,告诉浏览器,我响应报文发送完了,你准备关闭吧)
(4)客户端A发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)。发起方向被动方发送报文段,Ack、Seq。然后进入等待 TIME_WAIT 状态。被动方收到发起方的报文段以后关闭连接。发起方等待一定时间2MSL未收到回复,则正常关闭。(第四次挥手:由浏览器发起,告诉服务器,我响应报文接受完了,我准备关闭了,你也准备吧)
8.2 为什么连接的时候是三次握手,关闭的时候却是四次握手?
为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
8.3 为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。
所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。
MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
文章参考: 1、《在浏览器输入URL回车之后发生了什么?》www.bbsmax.com/A/obzbjwp3z…
2、《在浏览器输入URL回车之后发生了什么?(超详细版)》 www.bbsmax.com/A/B0zq0N3Zd…