张柏沛的个人IT技术博客-专注和分享PHP建站和Python技术的学习博客

正文内容

浏览器输入一个网址发生了什么(一) 封装http消息和dns请求

栏目:Linux 系列:浏览器输入一个网址发生了什么 发布时间:2021-07-21 12:43:32 浏览量:63

本系列文章围绕着“往浏览器输入网址后发生了什么”介绍计算机网络的相关基础知识。本文将介绍往浏览器中输入一个网址后客户端如何封装http消息和发送dns请求查询目标主机的ip。

 

往浏览器输入网址后发生了什么?

1.客户端(如浏览器)解析url

url的组成部分如下所示:

客户端会按照 协议、域名、文件路径以及请求参数 url进行解析(就是解析出以上信息)。

 

url如果没有以/结尾表示访问一个指定文件,以/结尾表示访问指定目录下的默认文件,例如: http://www.lab.glasscom.com/dir/ 访问的是/dir 目录下的index.html文件。

http://www.lab.glasscom.com/dir 访问的是 /dir文件。但是如果不存在 /dir文件,则会把它当做是目录处理,因而会访问/dir/下的默认文件

 

2. 生成http请求消息

解析完url后,客户端会根据请求的类型(这里以GETPOST为例)生成http请求消息。http请求消息和响应消息如下所示:

 

 

PSget请求没有消息体,post才有。

消息头就是我们所说的header字段,包含诸如Content-TypeCookieHost等内容。

请求行的URI包括文件路径和请求参数。

请求消息和响应消息的不同仅在第一行

一个请求消息中只能写一个URI

 

如下为getpost请求报文格式:

客户端会根据上述(a)的格式生成http消息。

 

* 头信息列举:

通用头

 

 

请求头

 

 

响应头

 

响应消息中的状态码概述

 

 

 

3. 向DNS服务器查询域名对应IP

客户端生成http消息后会委托操作系统将消息发送给web服务器。操作系统拿到http报文后为了将其发送给web服务器,会先根据域名查询目标主机的IP地址。

 

* 简单了解IP相关知识

在网络中,所有设备都会被分配一个IP地址,IP地址相当于是服务器的坐标,客户端得知这个坐标才能将消息发送到服务器主机。

实际的IP是一串32比特的数字(IPv4标准),并按8比特分为4组,每组用原点隔开,每组以十进制表示。除了IPv4标准外还有IPv6标准,IPv6下的IP地址则是128比特的长度用于支持更多可能的地址,这里只介绍IPv4下的内容。

IP地址分为网络号和主机号两部分,网络号代表主机所在的子网网络,子网与子网间通过路由器和集线器连接和通信,主机号代表某台主机在子网中的具体位置。

IP地址被分为A~E类,每类的网络号和主机号长度是不定的,例如CIP的前3个字节是网络号,第4个字节是主机号;而BIP地址前2个字节是网络号,后两个字节是主机号。

IP地址会用附加信息来表示哪部分是IP的网络号,哪部分是IP的主机号。这个附加信息就是子网掩码。子网掩码是一串与IP长度相同的32比特数字,也分为主机号和网络号,其中左边一半全为1,右边一半全为0,全为1的部分为网络号,全为0的部分为主机号。

例如: 10.11.12.13/255.255.255.0 255.255.255.0就是子网掩码,它的前3字节是1,第四字节为0,因此表示10.11.12.13中前3字节是网络号,第4字节是主机号。

 

此外还可以用 网络号比特数 表示子网掩码,如 2424表示前三字节为网络号(8*3)16表示前两个字节为网络号(8*2)8表示只有第一个字节是网络号。

域名也代表某一服务器的地址,但域名的使用是为了方便人类的记忆,而IP才是服务器所在主机的真正位置。

 

回到正题。

从域名解析为IP就涉及到DNS(域名解析)

为了得到域名对应的IP,客户端(浏览器)在将http请求委托给操作系统发送前会查询浏览器的DNS缓存找域名对应IP,如果命中缓存则客户端会将IP带给操作系统,没有命中则操作系统会查找本机的DNS缓存,如果还是没有命中,操作系统就会通过DNS解析器DNS服务器发起DNS请求。

 

* 关于DNS解析器

DNS解析器本质上是操作系统socket库中的一段程序,用于向dns服务器发送查询请求并获取域名对应的IP并返回给客户端。而socket库是用于调用网络功能的通用程序组件。

客户端通过DNS解析器发起dns请求的过程如下所示

客户端(浏览器)委托操作系统调用socket库的gethostbyname()这个系统调用函数,此时用户程序(浏览器)的工作会暂停并切换到操作系统的dns解析器运行,即用户态切换到内核态。

 

DNS解析器根据浏览器提供的域名生成DNS查询消息(DNS查询报文)并交给操作系统中的TCP/IP协议栈,由协议栈通过网卡以UDP传输的方式发送给DNS服务器。在这里,操作系统必须得知道DNS服务器的IP,这样操作系统才该把报文发送给那DNS服务器,而这个DNS服务器的IP是已经事先设置好的,如下所示

而这个设置好的DNS服务器一般是距离客户端主机所在城市内不远处的一个DNS服务器,我们称之为本地DNS服务器。

 

 

发送DNS查询报文后,DNS服务器会返回对应域名的IP地址给协议栈(至于DNS服务器根据域名返回对应ip的过程会在之后介绍),并按原路返回给DNS解析器,解析器将IP写入到浏览器指定的内存地址中(从内核态切回用户态),这样当该浏览器待会再想知道这个域名的IP时就直接从用户程序内存中取即可,无需在做DNS查询。此外,操作系统和浏览器还会对这个域名与IP的映射关系做缓存,即使关闭了浏览器下次再打开并请求也无需做DNS查询请求。除非缓存时间过期。

得到IP的值的浏览器终于可以开始发送HTTP请求消息。

 

4. DNS报文在多个DNS服务器间的传递

当客户主机的操作系统将DNS查询报文发送给本地DNS服务器到DNS服务器返回IP给客户端主机这段期间发生了什么?这里需要介绍一下DNS查询报文的内容和DNS服务器。

 

* 简述DNS查询报文的内容

主要包含3部分内容

域名

class

class永远是IN,表示互联网网络

记录类型

表示域名对应何种类型的记录(即告诉DNS服务器,根据传过来的域名,它应该返回什么类型的响应内容)。

 

dns服务器中保存着多条资源记录,资源记录不只包括域名与IP的映射,但包括域名与其他信息的映射,而资源记录中保存的到底是域名与什么信息的映射取决于记录类型

 

如类型是A表示该条记录是域名对应的IP地址;

类型为MX,是该域名对应的邮箱服务器域名;

类型为CNAME,该记录是一个别名域名对应的真正域名;

类型为NS时该记录存着要查询的域名是由哪个DNS服务器解析的(也就是记录着一个目标DNS服务器的域名),此时这个DNS服务器应该还保存着目标DNS服务器的域名与IP的映射。如下所示:

baidu.com IN NS ns1.domain.com

baidu.com IN NS ns2.domain.com

ns1.domain.com IN A 111.222.111.111

ns2.domain.com IN A 123.111.222.111

 

除了上述类型,还有其他的记录类型。感兴趣的朋友可以自行查阅。

 

 

* 域名层级

一个域名的层级从左到右依次提升,每个层级用.分开。以www.abc.com为例,com是顶级域名,com域的下一层是abc域,再下一层是www这个名字。

 

* DNS服务器

DNS服务器本质是一个存储着域名与相应信息映射关系具有层级的、分布式数据库集群

 

 

** 存储着域名与相应信息映射关系

DNS服务器里面保存的数据我们称之为资源记录,如下所示:

当带有 域名、class和记录类型 的请求报文到达DNS服务器后,它会根据这3个信息从资源记录中找到这3个字段都匹配的记录返回给客户端。相当于 select `响应数据` from where `域名`="xxx" and `class`="xxx" and `记录类型`="xxx";

 

** 具有层级的、分布式数据库集群

分布式:无论从服务器负载、数据备份和故障时高可用的角度来说,所有的域名信息不可能保存到一台DNS服务器上,而是由多台分布到世界上多台DNS服务器共同维护。

具有层级:DNS服务器是具有层级的,其层级是根据域名的层级来划分,由上到下分为 根域名DNS服务器、顶级域名DNS服务器和权威DNS服务器。

 

全世界的根域DNS服务器大概有十几台。

每一层DNS服务器都保存着下一层DNS服务器的所有IP地址,并且所有层级的每一台DNS服务器会保存所有根域的DNS服务器IP。这么一来就能做到在本地DNS服务器能找到根域DNS服务器IP,再从根据服务器逐层往下找到其他DNS服务器。

 

如下图所示:

 

有了上面的扩展知识后,我们再来说DNS报文发送到本地DNS服务器后发生了什么:

www.lab.glasscom.com为例

· DNS查询报文到达本地DNS服务器后,如果本地DNS服务器没有记录目标域名对应的IP,则会将查询转发给根DNS服务器;

· 根域DNS服务器也没有该域名的资源记录,但判断出其顶级域为com,所以会把com域的DNS服务器的IP返回给本地DNS服务器;

· 本地DNS服务器再根据这个IPcom域的DNS服务器发起查询请求,但com域的DNS服务器也没有www.lab.glasscom.com的资源记录,但判断出该域名的权威域名为glasscom.com,找到了glasscom.com域的DNS服务器的IP地址并返回。

· 本地DNS服务器向glasscom.com域的DNS服务器发起DNS查询请求,查到了www.lab.glasscom.comIP

· 最终本地DNS服务器将目标IP返回给客户端主机,同时本地DSN服务器也会对该域名的IP映射进行缓存。下一次被访问到相同的域名时直接查询DNS缓存而不再向根域DNS服务器发起请求

上面这种DNS查询方式是迭代查询,每次都是由本地DNS服务器发起请求;

此外还有其他查询方式如递归查询,以及直接查询DNS缓存。

下面我们看看递归查询和迭代查询的区别:

 

递归查询

由本机查询本地DNS服务器,本地DNS服务器如果没有命中目标域名则向根服务器请求,根服务器根据顶级域名找到对应的顶级域名服务器的IP并向该顶级域名服务器发送请求,同理顶级域名服务器再向对应的权威域名服务器发送DNS查询请求的到目标地址IP,并将其原路返回给本机。

如下图展示了递归查询过程:

 

 

迭代查询

迭代查询就是上文中提到过的查询方式,本机请求本地域名服务器,本地域名服务器请求根域名服务器拿到顶级域名服务器的ip,本地域名服务器再去请求顶级域名服务器拿到权威域名服务器的ip,本地域名服务器再去请求权威域名服务器拿到目标ip,再返回给本机。

如下图

如果您需要转载,可以点击下方按钮可以进行复制粘贴;本站博客文章为原创,请转载时注明以下信息

张柏沛IT技术博客 > 浏览器输入一个网址发生了什么(一) 封装http消息和dns请求

热门推荐