从用户的角度出发,得益于各大浏览器厂商的不懈努力,这一切都显得已经很理所固然,输入一个地址,访问网络,显示一个绚丽多彩的界面,你能够能够在上面浏览视频,看文章,甚至玩游戏。
可是站在开发者的角度,这是一个纵观全局的大问题,每个步骤都是一个能够延伸的话题。对于项目的优化都离不开这里的方方面面,是有深刻理解的价值的。咱们能够从一个总览出发,看看背后发生了什么。
首先咱们要知道什么是DNSweb
域名系统(英文:Domain Name System,缩写:DNS)是互联网的一项服务。它做为将域名和IP地址相互映射的一个分布式数据库,可以令人更方便地访问互联网。DNS使用TCP和UDP端口53。当前,对于每一级域名长度的限制是63个字符,域名总长度则不能超过253个字符。 --维基百科
域名解析的过程是逐级查询的chrome
dscacheutil -flushcache
咱们能够经过dig命令查看域名解析的记录数据库
dig math.stackexchange.com
咱们重点看返回的应答,会看到有四条记录,返回了该网址的四个IPsegmentfault
;; ANSWER SECTION: math.stackexchange.com. 31 IN A 151.101.1.69 math.stackexchange.com. 31 IN A 151.101.129.69 math.stackexchange.com. 31 IN A 151.101.193.69 math.stackexchange.com. 31 IN A 151.101.65.69
31是TTL的值,表示该域名的缓存时间,即该时间内不用从新查询。A是该DNS查询的记录类型,表示返回一个IPv4格式的地址。还有其余记录类型诸如 NS(返回查询的服务器地址)、AAAA(返回IPV6格式的地址)、CNAME(域名的别名)等。浏览器
拿到了要请求的资源服务器IP后,浏览器经过操做OS的socket与服务器进行TCP链接(通常来讲操做系统已经封装好了TCP/IP等协议,提供套接字给应用去使用,该部分涉及到标准网络模型的知识,另外再开篇拓展。)缓存
这个链接就是咱们所熟知的三次握手
本机主动打开链接服务器
须要注意的一点是,有一些文章对ACK标识位 和 ack(Acknowledgement Number)的解释比较模糊,有一些画图的时候干脆就写在一块儿了。虽然这二者有关联,但不是同一个东西,搞清楚这个误区能够更方便去理解。还有一些会把第二次握手描述成两个包(好比某百科……),实际上这也是不正确的网络
理解了这两点,也就不难理解为何三次握手分别是SYN、ACK/SYN、ACK了。并发
TCP的头部固定有20个字节,其中分配了6bits给TCP FLAG,组合起来用来表示当前包的类型。分别是
URGACKPSHRSTSYNFIN(CWRECE放在保留位,暂不考虑)socket
至此咱们了解了一个TCP 链接的过程,通道通了,是时候利用这个通道送东西了。
咱们从传输层再回到应用层。
超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协做式和超媒体信息系统的应用层协议[1]。HTTP是万维网的数据通讯的基础。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。经过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。 --wiki
咱们用 https://www.segmentfault.com 举例子。
在应用层,浏览器会分析这个url,并设置好请求报文发出。请求报文中包括请求行、请求头、空行、请求主体。https默认请求端口443, http默认80。
服务端收到请求以后,会根据url匹配到的路径作相应的处理,最后返回浏览器须要的页面资源。浏览器会收到一个响应报文,而所须要的资源就就在报文主体上。与请求报文相同,响应报文也有与之对应的起始行、首部、空行、报文主体,不一样的地方在于包含的东西不同。
请求是浏览器的一个优化点,咱们能够经过缓存来减小没必要要的请求,进而加快页面的呈现。经过简单地设置http头部可使用缓存的功能。通常来讲有三种设置的方式
服务器在返回资源的时候设置Last-Modify当前资源最后一次修改的时间,浏览器会把这个时间保存下来,在下次请求的时候,请求头部If-Modified-Since 会包含这个时间,服务端收到请求后,会比对资源最后更新的时间是否在If-Modified-Since设置的时间以后,若是不是,返回304状态码,浏览器将从缓存中获取资源。反之返回200和资源内容。
根据资源标识符来肯定文件是否存在修改,服务器每一次返回资源,都会在Etag中存放资源的标识符,浏览器收到这个标识符,在下一次请求的时候将标识符放在If-None-Match中,服务端将判断是否匹配,若是不匹配,返回200以及新的资源,反之返回304,浏览器从缓存中获取资源
首先这不是一种方法,而是协议更替中的一种演化。
在http 1.0的时代,咱们基于Pragma 和 Expires 控制缓存的生命周期。咱们能够经过设置Pragma为no-cache关闭缓存功能,一样也能够在Expires中设置一个缓存失效的时间。须要注意的是,这个失效的时间是相对于服务器的实践而言的,若是人为地改变了客户端的时间,是会致使缓存失效的。
因此,为了解决这个问题,HTTP1.1的协议加入了Cache-Control,经过设置Cache-Control的max-age能够控制缓存的周期。在这个周期内,资源是新鲜的,浏览器再一次须要使用资源的时候,就不会发出请求了。
至此浏览器已经拿到了一个HTML文档,并为了呈现文档而开始解析。呈现引擎开始工做,基本流程以下(以webkit为例)
从构建DOM树到呈现的过程以下
op=>operation: Parsing HTML to construct the DOM tree op1=>operation: Render Tree construction op2=>operation: Layout of the Render Tree op3=>operation: Painting the Render Tree op->op1->op2->op3
须要注意的是,这是一个渐进的过程,呈现引擎为了力求显示的及时,会在文档请求不彻底的状况下就开始渲染页面,同时,若是在解析的过程当中遇到script的时候,文档的解析将会中止下来,当即解析执行脚本,若是脚本是外部的,则会等待请求完成并解析执行。因此,为了避免阻塞页面地呈现,通常会把script脚本放在文档的最后。
在最新的HTML4和HTML5规范中,也能够将脚本标注为defer,这样就不会中止文档解析,而是等到解析结束后才执行。HTML5 增长了一个选项,可将脚本标记为async,以便由其余线程解析和执行。
如今的页面为了优化请求的耗时,默认都会开启持久链接(keep-alive),那么一个TCP链接确切关闭的时机,是这个tab标签页关闭的时候。这个关闭的过程就是著名的四次挥手。关闭是一个全双工的过程,发包的顺序的不必定的。通常来讲是客户端主动发起的关闭,过程以下。
假如最后一次客户端发出的数据seq = x, ack = y;
MSL: 全程Maximum Segment Lifetime,中文能够翻译为报文最大生存时间。等待是为了保证链接的可靠性,确保服务端收到ACK包,若是服务端没有收到这个ACK包,将会重发FIN包给客户端,而这个时间恰好是服务端等待超时重发的时间 + FIN的传输时间。