1.2 向DNS服务器查询Web服务器的IP地址
1.2.1 IP 地址的基本知识
委托操作系统发送消息前需要根据域名查询 IP 地址。
生成 HTTP 消息之后,需要委托操作系统将消息发送给Web 服务器。
浏览器能够解析网址并生成 HTTP 消息,但它本身不能消息发送到网络中,这一功能需要委托操作系统来实现。
在委托操作系统发送消息时,必须要提供通信对象的 IP 地址,所以在委托前需要查询网址中服务器域名对应的 IP 地址。
因此在生成 HTTP 消息之后,下一个步骤就是根据域名查询 IP 地址。
在讲解这一操作之前,让我们先来简单了解一下 IP 地址。
IP地址的基本概念
TCP/IP的基本思路
互联网和公司内部的局域网都是基于 TCP/IP 的思路来设计的,所以我们先来了解 TCP/IP 的基本思路。
TCP/IP 的结构如图下图所示,是由一些小的子网通过路由器连接起来组成一个大的网络。
这里的子网可以理解为用集线器连接起来的几台计算机,我们将它看作一个单位,称为子网。
将子网通过路由器连接起来,就形成了一个网络。
在网络中,所有的设备都会被分配一个地址,这个地址就相当于现实中某条路上的“×× 号 ×× 室”。
其中“号”对应的号码是分配给整个子网的,而“室”对应的号码是分配给子网中的计算机的,这就是网络中的地址。
“号”对应的号码称为网络号,“室”对应的号码称为主机号,这个地址的整体称为 IP 地址。
IP地址的格式
前面这些就是 TCP/IP 中 IP 地址的基本思路。再来看一下实际的 IP 地址。
如下图所示,实际的 IP 地址是一串32 比特的数字,按照 8 比特(1 字节)为一组分成 4 组,分别用十进制表示然后再用圆点隔开。
这就是我们平常经常见到的 IP 地址格式,但仅凭这一串数字我们无法区分哪部分是网络号,哪部分是主机号。
在 IP 地址的规则中,网络号和主机号连起来总共是 32 比特,但这两部分的具体结构是不固定的。
子网掩码
在组建网络时,用户可以自行决定它们之间的分配关系,因此,我们还需要另外的附加信息来表示 IP地址的内部结构。
这一附加信息称为子网掩码。子网掩码的格式如下图所示,是一串与 IP 地址长度相同的 32 比特数字,其左边一半都是 1,右边一半都是0。
其中,子网掩码为 1 的部分表示网络号,子网掩码为 0 的部分表示主机号。
将子网掩码按照和 IP 地址一样的方式以每 8 比特为单位用圆点分组后写在 IP 地址的右侧,这就是图上图的方法。
这种写法太长,我们也可以把 1 的部分的比特数用十进制表示并写在 IP 地址的右侧,如下图所示。
这两种方式只是写法上的区别,含义是完全一样的。
主机号全为0或1的情况
主机号部分的比特全部为 0 或者全部为 1 时代表两种特殊的含义。
主机号部分全部为 0 代表整个子网而不是子网中的某台设备。
此外,主机号部分全部为 1 代表向子网上所有设备发送包,即广播,如下图所示。
1.2.2 域名和 IP 地址并用的理由
TCP/IP 网络是通过 IP 地址来确定通信对象的,不知道 IP 地址就无法将消息发送给对方。
因此,在委托操作系统发送消息时,必须要先查询好对方的 IP 地址。
为什么不直接输入IP地址访问服务器
要记住一串由数字组成的 IP 地址也非常困难相比 IP 地址来说,网址中使用服务器名称比较好。
为什么不直接使用域名进行通信
IP 地址的长度为 32 比特,也就是 4 字节,相对地,域名最短也要几十个字节,最长甚至可以达到 255 字节。
这增加了路由器的负担,传送数据也会花费更长的时间。路由器的速度是有极限的,因此我们不应该再采用效率更低的设计。
使用DNS查询域名和IP地址
为了填补两者之间的障碍,需要有一个机制能够通过名称来查询 IP 地或者通过 IP 地址来查询名称。
这样就能够在人和机器双方都不做出牺牲的前提下完美地解决问题。这个机制就是 DNS。
DNS:Domain Name System,域名服务系统。
将服务器名称和 IP 地址进行关联是 DNS 最常见的用法,但 DNS 的功能并不仅限于此,它还可以将邮件地址和邮件服务器进行关联,以及为各种信息关联相应的名称。
1.2.3 Socket 库提供查询 IP 地址的功能
DNS解析器
浏览器是如何向 DNS 服务器发出查询的
向 DNS 服务器发出查询,也就是向 DNS 服务器发送查询消息,并接收服务器返回的响应消息。
换句话说,对于 DNS 服务器,我们的计算机上一定有相应的 DNS 客户端,而相当于 DNS 客户端的部分称为 DNS 解析器,或者简称解析器。
通过 DNS 查询 IP 地址的操作称为域名解析,负责执行解析(resolution)这一操作的就叫解析器(resolver)。
解析器实际上是一段程序,它包含在操作系统的 Socket 库中,在介绍解析器之前,我们先来简单了解一下 Socket 库。
Socket库
库就是一堆通用程序组件的集合,其他的应用程序都需要使用其中的组件。
Socket 库也是一种库,其中包含的程序组件可以让其他的应用程序调用操作系统的网络功能。
而解析器就是这个库中的其中一种程序组件。
1.2.4 通过解析器向 DNS 服务器发出查询
解析器的用法非常简单。Socket 库中的程序都是标准组件,只要从应用程序中进行调用就可以了。
具体来说,在编写浏览器等应用程序的时候,只要像下图这样写上解析器的程序名称“gethostbyname”以及 Web 服务器的域名“www.lab.glasscom.com”就可以了,这样就完成了对解析器的调用。
调用解析器后,解析器会向 DNS 服务器发送查询消息,然后 DNS 服务器会返回响应消息。
响应消息中包含查询到的 IP 地址,解析器会取出 IP地址,并将其写入浏览器指定的内存地址中。
只要运行上图中的这一行程序,就可以完成前面所有这些工作,我们也就完成了 IP 地址的查询。
接下来,浏览器在向 Web 服务器发送消息时,只要从该内存地址取出 IP 地址,并将它与 HTTP 请求消息一起交给操作系统就可以了。
1.2.5 解析器的内部原理
由于调用了其他程序,原本运行的程序进入暂停状态,而被调用的程序开始运行,被称为“控制流程转移”。
应用程序调用解析器
网络应用程序调用解析器时,程序的控制流程就会转移到解析器的内部。
一般来说,应用程序编写的操作内容是从上往下按顺序执行的,当到达需要调用解析器的部分时,对应的那一行程序就会被执行,应用程序本身的工作就会暂停,如下图①所示。
然后Socket库中的解析器开始运行如下图②所示,完成应用程序委托的操作。
解析器生成查询消息
当控制流程转移到解析器后,解析器会生成要发送给 DNS 服务器的查询消息。
这个过程与浏览器生成要发送给 Web 服务器的 HTTP 请求消息的过程类似,
解析器会根据 DNS 的规格,生成一条表示“请告诉我 www.lab.glasscom.com 的 IP 地址”的数据(HTTP 消息是用文本编写的,但 DNS 消息是使用二进制数据编写的),并将它发送给 DNS 服务器,如下图③所示。
委托操作系统的协议栈发送消息
发送消息这个操作并不是由解析器自身来执行,而是要委托给操作系统内部的协议栈来执行。
这是因为和浏览器一样,解析器本身也不具备使用网络收发数据的功能。
协议栈
操作系统内部的网络控制软件,也叫“协议驱动”“TCP/IP驱动”等。
协议栈通过网卡发送消息
解析器调用协议栈后,控制流程会再次转移,协议栈会执行发送消息的操作,然后通过网卡将消息发送给 DNS 服务器
DNS服务器根据消息进行查询
当 DNS 服务器收到查询消息后,它会根据消息中的查询内容进行查询。
总之,如果要访问的 Web 服务器已经在 DNS 服务器上注册,那么这条记录就能够被找到,然后其 IP 地址会被写入响应消息并返回给客户端。
DNS服务返回响应消息
接下来,消息经过网络到达客户端,再经过协议栈被传递给解析器,如下图⑦⑧所示。
协议栈传递给解析器,解析器取出IP
然后解析器读取出消息取出 IP 地址,并将 IP 地址传递给应用程序如下图 ⑨所示。
解析器将IP存入指定内存
实际上,解析器会将取出的 IP 地址写入应用程序指定的内存地址中。
到这里,解析器的工作就完成了,控制流程重新回到应用程序(浏览器)。
现在应用程序已经能够从内存中取出 IP 地址了,所以说 IP 地址是用这种方式传递给应用程序的。
DNS服务器IP是系统设置好的
向 DNS 服务器发送消息时,我们当然也需要知道 DNS 服只不过这个 IP 地址是作为 TCP/IP 的一个设置项目事先设置好的,不需要再去查询了。