在浏览器中输入一个网址后,发生了什么?
这是面试中一道非常经典的问题。
当你在浏览器中输入一个网址,浏览器的处理过程如下:
-
第一步 浏览器查找该域名的 IP 地址
-
第二步 浏览器根据解析得到的IP地址向 web 服务器发送一个 HTTP 请求
-
第三步 服务器收到请求并进行处理
-
第四步 服务器返回一个响应
-
第五步 浏览器对该响应进行解码,渲染显示。
-
第六步 页面显示完成后,浏览器发送异步请求。
-
第七步 整个过程结束之后,浏览器关闭TCP连接。
下面对每个环节做进一步分析:
01 浏览器查找该域名的 IP 地址
DNS查找过程为:浏览器缓存->系统缓存->路由器缓存->ISP DNS缓存->递归搜索递归搜索过程为:从根域名服务器到*域名服务器到你查询的域名服务器。
浏览器缓存 首先是查找浏览器缓存,浏览器会缓存DNS记录一段时间,不同浏览器保存的时常不等(2分钟到30分钟不等)。
系统缓存 如果在浏览器缓存里没有找到需要的记录,浏览器会做一个系统调用来查找这个网址的对应DNS信息。
路由器缓存 如果在系统缓存里没有找到找到对应的IP,请求会发向路由器,它一般会有自己的DNS缓存。
ISP DNS服务器 如果在路由器缓存里还是没有对应的IP,请求会被发送到ISP。
根域名服务器 如果还是没有,请求将发向根域名服务器进行搜索。找不到就说明此域名不存在。
02 浏览器根据解析得到的IP地址向 web 服务器发送一个 HTTP 请求
可能会重定向响应
例如“http://facebook.com/”,服务器会给浏览器响应一个301永久重定向响应,这样浏览器就会访问“http://www.facebook.com/” 而非“http://facebook.com/”。
服务器重定向的原因有很多,举其中两个:
一:跟搜索引擎排名有关。你看,如果一个页面有两个地址,就像“http://www.facebook.com/” 和“http://facebook.com/”。搜索引擎会认为它们是两个网站,结果造成每一个的搜索链接都减少从而降低排名。
二:不同的地址会造成缓存友好性变差。当一个页面有好几个名字时,它可能会在缓存里出现好几次。
然后浏览器会跟踪重定向地址
浏览器会发送另一个获取请求到”http://www.facebook.com/”。
过程:
通过DNS获取到IP后,目标IP和本机IP分别与子网掩码相与的结果相同,那么它们在一个子网,那么通过ARP协议可以查到目标主机的MAC地址,否则的话,需要通过网关转发,也就是目标MAC是网关的MAC。
请求需要进行编码,生成一个HTTP数据包,依次打上TCP、IP、以太网协议的头部。其中TCP头部主要信息是本机端口和目标端口号等信息,用于标识同一个主机的不同进程,对于HTTP协议,服务器端的默认端口号是80,本机浏览器的话生成一个1024到65535之间的端口号。IP头部主要包含本地IP和目标IP等信息。以太网协议头部主要是双方的MAC地址,目标MAC可以由第一条所诉方法得到。以太网数据包的数据部分,最大长度为1500字节,所以如果IP包太大的话还要拆包,比如IP包5000字节,要分为4包,每一包都包含一个IP头部。
03 服务器收到请求并进行处理
负载均衡
网站可能会有负载均衡设备来平均分配所有用户的请求。
负载均衡,即对工作任务进行平衡,分摊到多个操作单元上执行,如图片服务器,应用服务器。可分为链路负载均衡,集群负载均衡,操作系统负载均衡
集群负载均衡又分为硬件负载均衡和软件负载均衡。
CDN
请求的数据可能存储在分布式缓存、静态文件或者数据库中。如果请求的数据是静态文件,如果在CDN上,那么CDN服务器又会处理这个用户的请求。如果在数据库中需要向数据库发起查询请求。
04 服务器返回一个响应
过程:
服务器返回一个 HTTP 响应,如果返回状态码304,浏览器可以直接使用之前缓存的资源。对于内容响应,浏览器需要进行响应解码,渲染显示。
05 浏览器对该响应进行解码,渲染显示。
过程:
在浏览器没有完整接受全部HTML文档时,它就已经开始显示这个页面了,如果是个静态的页面,拿到此就基本结束了。如果是是动态的,那么在浏览器显示HTML时,会获取嵌入在HTML中的对象,浏览器会发送获取请求来重新获得这些文件。这些请求都要经历一个和HTML读取类似的过程。
对于静态的页面内容,浏览器通常会进行缓存,而对于动态的内容,浏览器通常不会进行缓存。
06 页面显示完成后,浏览器发送异步请求。
过程:
页面显示完成后客户端仍与服务器端保持着联系。
它会持续与服务器保持联系来及时更新一些页面信息。在浏览器中执行的 JavaScript代码会给服务器发送异步请求。这个异步请求发送给特定的地址,它是一个按照程式构造的获取或发送请求。
07 整个过程结束之后,浏览器关闭TCP连接。
相关扩展:
ARP原理
-
每个主机都会在自己的ARP缓冲区中建立一个ARP列表,以表示IP地址和MAC地址之间的对应关系。
-
当源主机要发送数据时,首先检查ARP列表中是否有对应IP地址的目的主机的MAC地址,如果有,则直接发送数据,如果没有,就向本网段的所有主机发送ARP数据包,该数据包包括的内容有:源主机 IP地址,源主机MAC地址,目的主机的IP 地址。
-
当本网络的所有主机收到该ARP数据包时,首先检查数据包中的IP地址是否是自己的IP地址,如果不是,则忽略该数据包,如果是,则首先从数据包中取出源主机的IP和MAC地址写入到ARP列表中,如果已经存在,则覆盖,然后将自己的MAC地址写入ARP响应包中,告诉源主机自己是它想要找的MAC地址。
-
源主机收到ARP响应包后。将目的主机的IP和MAC地址写入ARP列表,并利用此信息发送数据。如果源主机一直没有收到ARP响应数据包,表示ARP查询失败。
RARP原理
RARP是逆地址解析协议,作用是完成硬件地址到IP地址的映射,主要用于无盘工作站,因为给无盘工作站配置的IP地址不能保存。
工作流程:在网络中配置一台RARP服务器,里面保存着IP地址和MAC地址的映射关系,当无盘工作站启动后,就封装一个RARP数据包,里面有其MAC地址,然后广播到网络上去,当服务器收到请求包后,就查找对应的MAC地址的IP地址装入响应报文中发回给请求者。因为需要广播请求报文,因此RARP只能用于具有广播能力的网络。
TCP三次握手和四次挥手
***seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;给字节编上序号后,就给每一个报文段指派一个序号;***seq就是这个报文段中的第一个字节的数据编号。
确认号ack:占4个字节,期待收到对方下一个报文段的第一个数据字节的序号;***表示报文段携带数据的第一个字节的编号;而确认号指的是期望接收到下一个字节的编号;因此当前报文段最后一个字节的编号+1即为确认号。
确认ACK:占1位,仅当ACK=1时,确认号字段才有效。ACK=0时,确认号无效
同步SYN:连接建立时用于同步序号。当SYN=1,ACK=0时表示:这是一个连接请求报文段。若同意连接,则在响应报文段中使得SYN=1,ACK=1。因此,SYN=1表示这是一个连接请求,或连接接受报文。SYN这个标志位只有在TCP建产连接时才会被置1,握手完成后SYN标志位被置0。
终止FIN:用来释放一个连接。FIN=1表示:此报文段的发送方的数据已经发送完毕,并要求释放运输连接
PS:ACK、SYN和FIN这些大写的单词表示标志位,其值要么是1,要么是0;ack、seq小写的单词表示序号。
TCP三次握手:
所谓的三次握手,是指建立一个TCP连接时,需要客户端和服务器端总共发送三个包,三次握手的目的是连接服务器的指定端口,建立TCP连接,并同步连接双方的***和确认号并交换TCP窗口大小信息,在SOCKET编程中,客户端执行connect()时,将会触发三次握手
解释:
ACK:TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1
SYN:在连接建立时用来同步序号,当SYN=1而ACK=0时,表明这是一个连接请求报文,对*同意建立连接,则应在响应报文中使SYN=1和ACK=1,因此,SYN置1就表示这是一个连接请求或连接接受报文
FIN:即终结的意思,用来释放一个连接,当FIN=1时,表明此报文段的发送方的数据已经发送完毕,并要求释放连接
为什么要进行三次握手(两次确认)?
主要是为了防止客户端发出的已失效的连接请求报文段突然又传送到了服务器端,因而产生错误,考虑一种正常情况,A发出连接请求,但因连接请求报文丢失而未收到确认,于是A再重传一次连接请求,后来收到了确认,建立了连接,数据传输完毕后,就释放了连接,A共发送了两个连接请求报文段,其中第一个丢失,第二个到达了B,正常,再考虑一种异常情况,即A发出的第一个连接请求报文段并没有丢失,而是在某个网络节点长时间滞留了,以致延误到连接释放以后的某个时间才到达B,本来这是一个早已失效的报文段,但B收到此失效的连接请求报文段后,会误以为是A又发出一次新的连接请求,于是就向A发出确认报文段,同意建立连接,假定不采用第三次握手,那么只要B发出确认,新的连接就建立了,一直等待A发送数据过来,使得B的许多资源就浪费了,所以采用三次握手的方法可以防止上述现象的发生,在刚才的情况下,A不会向B发出第二次确认,B由于收不到确认,就知道A并没有要求建立连接
TCP四次挥手:
TCP连接的拆除需要发送四个包,客户端或者服务器端均可主动发起挥手动作,在SOCKET编程中,任何一方执行close()即可产生挥手操作
解释:当A没有数据要发送时,就要释放A这边的连接,A会发送一个报文(没有数据),B收到后会给应用程序一个信,这时候A那边的连接已经关闭,即A不再发送信息(但仍可接收信息),A收到B的确认后进入等待状态,等待B请求释放连接,B数据发送完成后就向A请求连接释放,A收到后回复一个确认信息,并等待2MSL时间
为什么要等待呢?
考虑到这种情况,B向A发送释放连接请求,但这个报文丢失了,A没有接收到不会发送确认信息,B超时会重传,这时A在等待时间内还能够接收到这个请求,再回复一个确认就行了
另外服务器B存在一个保活状态,如果A突然死机了,保活时间到了后,B会发送探测信息,以决定是否释放连接
常见的状态代码、状态描述:
200 客户端请求成功
400 客户端请求有语法错误,不能被服务器理解
401 请求未经授权
403 服务器收到请求,但是拒绝提供服务
404 请求资源不存在
500 服务器发生了不可预期的错误
503 服务器当前不能处理客户端请求,一段时间后可能恢复正常
下一篇: 赵文银:云计算是以应用为目的