我思考了很多知识组织方法来帮助理解网络知识,比如按osi模型从底至上,或者按协议种类,或者按网络发展史。但最终我还是决定选择用这个经典的问题,将网络知识串成线。理解从输入url到看到页面的过程,弄明白这中间有哪些步骤,再仔细分析这些步骤的原理和行为,是我所能想到最清晰的一条知识脉络了。
这里我们就以访问阮一峰老师的一篇博文(HTTP 协议入门)来讲解吧,大家阅读本篇文章前也可以看看这篇文章。我们在浏览器输入“http://www.ruanyifeng.com/blog/2016/08/http.html”以后,浏览器如何为我们展现网页呢?
浏览器会对我们输入的url进行解析,主要将其分为下部分:协议、网络地址、资源路径。其中网络地址指示该连接网络上哪一台计算机,可以是域名或者IP地址,可以包括端口号;协议是从该计算机获取资源的方式,常见的是HTTP,HTTPS,FTP等。不同协议有不同的通讯内容格式;资源路径指示从服务器上需要获取资源的具体路径。 这里浏览器对输入的url解析为如下内容: url:http://www.ruanyifeng.com/blog/2016/08/http.html 协议:http 网络地址(网站名):www.ruanyifeng.com 资源路径:/blog/2016/08/http
当然,浏览器还知道端口信息和参数信息,但这一步还用不上。另外网络地址由服务器名:www和域名ruanyifeng.com组成。
浏览器理解用户输入的信息,知道用户想要用http访问一个网络地址是“www.ruanyifeng.com”的网站。那么如何找到这个地址呢,就像你打的回家,你跟司机说去阮老师家,他哪儿知道阮老师家是哪里呢?你得告诉他门牌号呀。网站服务器的门牌号就是IP地址。所有浏览器首先要确认的是域名所对应的服务器在哪里。将域名解析成对应的服务器IP地址这项工作,是由DNS服务器来完成的。 客户端收到你输入的域名地址后,它首先去找本地的hosts文件,检查在该文件中是否有相应的域名、IP对应关系,如果有,则向其IP地址发送请求,如果没有,再去找DNS服务器。一般用户很少去编辑修改hosts文件。 DNS服务器层级如下:
DNS服务器层级(转)
DNS查询的具体步骤如下:
DNS服务器递归查询和迭代查询(转) 浏览器客户端向本地DNS服务器发送一个含有域名http://www.cnblogs.com的DNS查询报文。本地DNS服务器把查询报文转发到根DNS服务器,根DNS服务器注意到其com后缀,于是向本地DNS服务器返回comDNS服务器的IP地址。本地DNS服务器再次向comDNS服务器发送查询请求,comDNS服务器注意到其http://www.cnblogs.com后缀并用负责该域名的权威DNS服务器的IP地址作为回应。最后,本地DNS服务器将含有http://www.cnblogs.com的IP地址的响应报文发送给客户端。 从客户端到本地服务器属于递归查询,而DNS服务器之间的交互属于迭代查询。 正常情况下,本地DNS服务器的缓存中已有comDNS服务器的地址,因此请求根域名服务器这一步不是必需的。
一些大型网站域名像wikipedia.org或者facebook.com整个域都映射到不止一个IP地址(土豪房子多),我们可以使用如下解决方法:
好了,阮老师家的门牌号知道了,正常来讲是可以出发了。可是对于网络有些不一样,你还需要指定端口号。端口号之于计算机就像窗口号之于银行,一家银行有多个窗口,每个窗口都有个号码,不同窗口可以负责不同的服务。端口只是一个逻辑概念,和计算机硬件没有关系。现在可以这么说,阮老师家好几扇们,办不同的业务走不同的门,你得告诉师傅你走那扇门,你要不说,就默认你是个普通客人,丢大门得了。http协议默认端口号是80。
好了,IP和端口都有了,能出发了么?师傅很热心,怕你去了对方家里没人啊,于是根据查到的信息给对方家里打了电话 师傅:“喂,家里有人没啊?有客人来拜访啊?” 对方:“有啊,来吧” 师傅:“好嘞”。 在http消息发送前,需要建立客户端与服务器的TCP链接,也就是进行所谓的三次握手。 TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出SYN连接请求后,等待对方回答SYN+ACK,并最终对对方的 SYN 执行 ACK 确认。这种建立连接的方法可以防止产生错误的连接,TCP使用的流量控制协议是可变大小的滑动窗口协议。
TCP三次握手
TCP三次握手的过程如下:
三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。
你们和阮老师家里互相确定了到访的事情后,你们终于开心地出发了。也就是说,与服务器建立了连接后,就可以向服务器发起请求了。这里我们先看下请求报文的结构:
请求报文结构-转
我们在chrome浏览器查看报文首部信息:
报文首部信息
我们可以从报文中看到发出的请求的具体信息。具体每个首部字段的作用,会开单章讲解。
好了,终于到了阮老师家,坐车去阮老师家的例子到此就结束了。不过我们的渲染页面的目的还没达到,现在请求只是成功达到了服务器,接下来服务器需要响应浏览器的请求。 服务器端收到请求后的由web服务器(准确说应该是http服务器)处理请求,诸如Apache、Ngnix、IIS等。web服务器解析用户请求,知道了需要调度哪些资源文件,再通过相应的这些资源文件处理用户请求和参数,并调用数据库信息,最后将结果通过web服务器返回给浏览器客户端。下面以静态渲染的页面为例,ajax渲染不需要在服务器做页面数据写入。
以静态页面渲染为例
在HTTP里,有请求就会有响应,哪怕是错误信息。这里我们同样看下响应报文的组成结构:
响应报文结构-转
在响应结果中都会有个一个HTTP状态码,比如我们熟知的200、301、404、500等。通过这个状态码我们可以知道服务器端的处理是否正常,并能了解具体的错误。 状态码由3位数字和原因短语组成。根据首位数字,状态码可以分为五类:
状态码
具体的状态码信息我会开单章。 另外还有一些其他信息(chrome中显示的response headers如下):
response headers
内容编码头部告诉浏览器响应体使用了gzip压缩算法,解压后就会看到你期望的HTML了。 除了压缩信息之外,头部还详细说明了是否和怎么缓存页面、设置cookies(在这个响应中没有)、隐秘信息等 或许有人注意到了设置了内容类型为text/html,这部分头部说明了浏览器将响应内容作为HTML渲染,而不是作为文件下载。浏览器将使用头部决定如何解释响应结果,当然也会考虑其他因素,比如URL的扩展情况。
为了避免服务器与客户端双方的资源占用和损耗,当双方没有请求或响应传递时,任意一方都可以发起关闭请求。 建立一个连接需要三次握手,而终止一个连接要经过四次挥手,这是由TCP的半关闭(half-close)造成的。具体过程如下图所示。
四次挥手
(1) 某个应用进程首先调用close,称该端执行“主动关闭”(active close)。该端的TCP于是发送一个FIN分节,表示数据发送完毕。 (2) 接收到这个FIN的对端执行 “被动关闭”(passive close),这个FIN由TCP确认。 注意:FIN的接收也作为一个文件结束符(end-of-file)传递给接收端应用进程,放在已排队等候该应用进程接收的任何其他数据之后,因为,FIN的接收意味着接收端应用进程在相应连接上再无额外数据可接收。 (3) 一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN。 (4) 接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN。
既然每个方向都需要一个FIN和一个ACK,因此通常需要4个分节。
注意:
(1) “通常”是指,某些情况下,步骤1的FIN随数据一起发送,另外,步骤2和步骤3发送的分节都出自执行被动关闭那一端,有可能被合并成一个分节。[2]
(2) 在步骤2与步骤3之间,从执行被动关闭一端到执行主动关闭一端流动数据是可能的,这称为“半关闭”(half-close)。
(3) 当一个Unix进程无论自愿地(调用exit或从main函数返回)还是非自愿地(收到一个终止本进程的信号)终止时,所有打开的描述符都被关闭,这也导致仍然打开的任何TCP连接上也发出一个FIN。
无论是客户还是服务器,任何一端都可以执行主动关闭。通常情况是,客户执行主动关闭,但是某些协议,例如,HTTP/1.0却由服务器执行主动关闭。
当浏览器获得一个html文件时,会“自上而下”加载,并在加载过程中进行解析渲染。 解析:
这一块的过程比较复杂,会开单章。
随着浏览器渲染HTML,浏览器会注意到有些标签需要请求其他URLs的资源,浏览器将会发送一个GET请求来重新获取每个文件 。比如js文件,css文件,图片资源等。 每个URLs会像获取HTML页面的过程一样获取相应资源。所以,浏览器会在DNS中查询域名,并向URL发送请求,进行重定向(其实以上步骤我是省略了重定向这一步的)等等以上步骤
当然,静态文件和动态网站不一样,它们允许被浏览器缓存。一些文件可能会根本不经过服务器,直接被从缓存中取出。因为响应结果中返回一个包含着Expires头的文件,所以浏览器知道要缓存一个文件多久。另外每个响应可能包含着ETag头,其作用类似版本号,如果浏览器发现已经拥有了一个文件的ETag,那么就会立即停止此文件传输。
在web2.0时代,即使在页面渲染后客户端还是持续与服务器端通信。这个模式被称为AJAX。我会开单章讲述。
以上步骤只是大略地解析了从浏览器输入url到最终页面展示在用户眼前的流程,更多细节我会开单章进行讲解。
"天龙八步"细说浏览器输入URL后发生了什么 【译】从输入URL到页面渲染完成 从输入 URL 到页面加载完的过程中都发生了什么事情? What really happens when you navigate to a URL 百度百科-TCP 浏览器加载、解析、渲染的过程