网络协议-网络层协议-IP协议
宽带上网是如何实现的
网络层是 TCP/IP 的心脏,主要负责终端节点之间的通信,把网络包从源主机发送到目标主机,所以这种通信也叫点对点的通信。这一层主要包含两个协议:IP 协议和 ICMP 协议,我们先来介绍 IP 协议。
网络层的作用
我们上一篇介绍的数据链路层只能在同一种数据链路上的节点之间进行通信,而一旦跨越多种数据链路,就需要借助网络层才能通信,网络层可以跨越不同的数据链路,实现两个节点之间的数据包传递,而这些不同的数据链路通常通过路由器来连接:
或者简单来说,在局域网内部需要数据链路层进行通信,而不同的局域网之间(互联网其实就是将多个不同的局域网连接起来实现互联)需要借助网络层才能通信,完整的计算机网络需要借助这两个分层才能最终完成通信。
IP地址
在计算机网络通信中,为了识别通信对端,需要一个类似于地址的识别码对节点进行标识,就好比找一个人需要门牌号一样,MAC 地址用于标识同一链路上的不同计算机,而网络层用于表示地址信息的是 IP 地址。
IP 地址用于在连接到网络的所有主机中识别出进行通信的目标地址,因此,在 TCP/IP 中所有主机或路由器必须设定自己的 IP 地址。IP 地址是 TCP/IP 通信的基石。
公网 IP 与私有 IP
起初,互联网中任何一台主机和路由器都必须配置一个唯一的 IP 地址,然而,随着互联网的发展,IP 地址不足的问题日趋显著,于是就有了一种新技术,它要求不为每一台主机或路由器分配一个固定的 IP 地址,而是在必要的时候只为相应数量的设备分配唯一的 IP 地址。
尤其对那些没有连接到互联网的独立网络中的主机,只要保证在这个网络内地址唯一,可以不用考虑互联网即可配置相应的 IP 地址。不过,即使两个独立网络各自随意设置 IP 地址,也可能会出问题,比如两个独立网络互连时地址冲突,或者由于某种原因,需要连接到互联网,于是又出现了私有网络的 IP 地址,它的范围如下:
包含在这个范围内的 IP 地址都属于私有 IP,而在此之外的 IP 地址称为全局 IP,也叫公网 IP。
私有 IP 最早没有准备连接互联网,而只用于互联网之外的独立网络,不过当一种能够互换私有 IP 与公网 IP 的 NAT 技术诞生以后,配有私有地址的主机与配有全局地址的互联网主机实现了通信。
现在,每个学校、公司、家庭内部采用的正是在每个终端设置私有 IP 地址,在路由器或必要的服务器上设置公网 IP 地址,配置私有 IP 地址的主机连网时,通过 NAT 进行通信。
公网 IP 地址基本要在整个互联网内保持唯一,但私有 IP 地址不需要,只要在同一个域内保持唯一即可。在不同的域内出现相同的私有 IP 地址不影响使用。
家用宽带上网实现
有了上面的知识储备,想必你已经对我们平时公司、学校、家庭如何实现宽带上网有些眉目了,下面学院君就来给大家捋一下。
在世界范围内,全局 IP 地址由 ICANN(互联网名称与数字地址配置机构)管理,在中国,由其下属 CNNIC 这个机构负责分配国内的公网 IP 地址分配。
在互联网广泛商用之前,用户需要直接向 CNNIC 申请公网 IP 地址才能上网,随着 ISP(互联网服务提供商,比如电信、联通、移动、华数)的出现,在向 ISP 申请接入互联网的同时还会申请公网 IP 地址,这种情况下,ISP 其实充当了用户与 CNNIC 之间的代理。
对于 FTTH(光纤到户) 和 ADSL 宽带服务(目前比较常见的两种宽带服务),网络服务提供商会直接给用户分配公网 IP 地址,并且每次用户重新连接互联网时,该 IP 地址都可能发生变化,这时的 IP 地址由提供商维护,不需要用户自行申请。当然这个公网 IP 地址是分配到路由器上的。
而我们通过有线或无线方式连接到路由器的计算机和手机的 IP 地址,则是由 DHCP 动态分配的私有 IP 地址。关于 DHCP 动态分配 IP 地址我们后面会单独介绍。
现在,一般只有在需要固定 IP 的情况下才需要申请公网 IP 地址,比如服务器、云主机等托管网站的主机节点。
好了,有了上面的介绍,想必你应该对笔记本、台式机等计算机终端以及手机如何通过 IP 地址连接上互联网进行通信有了比较清楚的了解了吧,当然,这还只是一个比较感性的了解,我们继续从技术层面来理性分析基于 IP 协议的网络层通信是如何实现的。
IP 地址详解
我们将深入探讨 IP 地址的格式、组成、分类、广播以及子网掩码等技术细节。
IP 地址的格式
IP 地址目前分为 IPv4 和 IPv6 两种类型,目前主流的还是 IPv4 地址,后面的分享也主要基于 IPv4。
在计算机内部,IPv4 地址由 32 位二进制数字表示,为了方便人类识别,通常将其按照 8 位一组,分为 4 组,每组用 . 分隔,并将每组内的二进制数转化为十进制数,这样就有了我们常见的 IP 地址(IPv4)格式:
同时,这也是一个私有 IP 地址。
注:后面的分享中,我们默认约定 IP 地址就是代指 IPv4 地址。
IP 地址一般配置在网卡上,一般一块主机网卡会配置一个 IP 地址(也可以配置多个),而一台路由器通常会配置两块以上的网卡(因为路由器连接的是两个网段):
IP 地址的组成
IP 地址由网络标识(网络地址)和主机标识(主机地址)两部分组成。
网络地址用于标识节点所属的数据链路,一般不同的局域网之间网络地址必须不同,而同一个局域网内的主机必须有相同的网络地址;主机地址则用于标识同一个局域网内的不同主机,它们的主机地址不能重复。这样综合起来,我们就可以通过设置网络地址和主机地址来确保在相互连接的网络中每个节点的 IP 地址都不会重复。
以上面图示的 IP 地址为例,192.168.31
是网络地址,218 则是主机地址。起初,我们通过 IP 地址分类来区分网络地址和主机地址,现在通常通过子网掩码区分它们。下面我们就分别来介绍下 IP 地址分类和子网掩码。
IP 地址的分类
按照网络层次和规划的子网大小,通常将 IP 地址分为以下4类:
- A 类地址:首位以 0 开头,第 1-8 位是网络地址,后24位是主机地址,0.0.0.0~127.0.0.0 是 A 类的网络地址,可容纳 16777214(224-2) 个主机地址;
- B 类地址:前两位以 10 开头,第 1-16 位是网络地址,后 16 位是主机地址,128.0.0.0~191.255.0.0 是 B 类的网络地址,可容纳 65534(216-2) 个主机地址;
- C 类地址:前三位以 110 开头,第 1-24 位是网络地址,后 8 位是主机地址,192.168.0.0~239.255.255.0 是 C 类的网络地址,可容纳 254(28-2) 个主机地址;
- D 类地址:前四位以 1110 开头,第 1-32 位是网络地址,没有主机地址,224.0.0.0~239.255.255.255 是 D 类的网络地址,常用于多播;
要用比特位标识主机地址时,不可以全部为 0 或 1,因为全部为 0 只有在表示对应的网络地址或 IP 地址不可获知的情况下才用,而全部为 1 的主机地址通常作为广播地址。因此,在分配的时候,要去掉这两种情况(这就是为什么上面都做了-2的处理)。
子网掩码
很显然,如果以上面 A、B、C 三类来划分子网的话,存在着 IP 地址的浪费,全世界 IP 地址的上限是 43 亿(2的32次方),如果按照 A 类来划分,全世界只能划分出 128 个子网(2的7次方),这显然不够;如果是办公室、学校这样的局域网来说,B 类地址的主机承载容量显得太大;如果是在家庭这种小型的局域网,即使是 C 类地址都有着极大的浪费。
因此,为了解决上述问题,我们通过一种叫做「子网掩码」的识别码将子网网络地址细分为比 A、B、C 类粒度更小的网络。这种方式会将原来的 A、B、C 类主机地址的一部分也作为网络地址,从而让 IP 地址的网络地址和主机地址不再受限于 IP 地址的分类,将原有网络划分为更多的子网。
引入子网以后,原始的 IP 地址就要通过两部分来识别,一种是 IP 地址本身,一种是标识网络地址部分的子网掩码:
子网掩码和 IP 地址一样也是由 32 位二进制数表示,格式和 IP 地址类似,只不过其对应 IP 地址网络地址部分的位都是 1,主机地址部分的位都是 0,我们将 IP 地址与子网掩码做按位与运算,就可以计算出该 IP 地址的网络地址部分。
对于子网掩码,一般常见的有两种表示方式,一种是上面这种分两行的表示方式,还有一种是在 IP 地址后面追加网络地址位数,并通过 /
分隔开:
192.168.31.218/24
有了子网掩码,我们就可以按照需要将子网按照任何维度进行划分了。
在此基础上,为了解决全世界 IPv4 地址数量有限的问题,还诞生了 CIDR(无类型域间选路)和 VLSM(可变长子网掩码)技术,但是 IPv4 地址绝对数本身有限的事实无法改变,因此又有了 IPv6 地址。
公网 IP 和私有 IP,诞生的初衷也是为了解决 IPv4 地址不够用的问题,不同局域网之间的私有 IP 可以重复。
IPv6 地址简介
IPv6 是为了从根本上解决 IPv4 地址耗尽的问题而被标准化的网际协议。
IPv4 的长度是 4 个 8 位字节,总共 32 位,IPv6 的长度是其 4 倍,即 128 位,一般写成 8 个 16 位字节:
其中 inet6
后面就是 IPv6 的地址。
IPv6 地址可以容纳的设备数是个天文数字(2的128次方),足以满足可预见的未来人类对 IP 地址的需求。但是从 IPv4 切换到 IPv6 是一件极其耗时的事情,需要将所有主机和路由器的 IP 地址进行重新设置。因此,现在主流的 IP 地址还都是 IPv4 地址。
广播地址和环回地址
广播地址用于在同一个局域网中相互连接的主机之间发送数据。IP 地址中的主机地址部分全部设置为 1,就成为了广播地址。本地广播会被路由器屏蔽,不会到达外部网络。
环回地址是在同一台计算机内部的程序之间进行网络通信时所使用的默认地址,一般使用一个特殊的 IP 地址 127.0.0.1
作为环回地址,该地址还有一个与之具有相同意义的主机名 localhost
,使用这个 IP 地址或主机名,数据包不会流向网络。
路由控制详解
IP 地址是网络层的基础,要真正将数据包从发送端成功发送到目标主机,还需要通过路由控制。现在我们来介绍路由控制的概念及其跳转流程。
路由控制定义
发送数据包时使用的地址就是 IP 地址,然而仅仅有 IP 地址还不足以将数据包发送到目标地址,在数据包发送过程中还需要指明下一跳路由器或主机,以便发往最终目标地址。
在这里我们需要先了解「跳」的概念,「跳」是网络中的一个区间(网段),IP 数据包正是在网络中一个个跳之间转发,因此 IP 路由也叫多跳路由,在每一个区间内决定着包在下一跳被转发的路径:
在以太网等数据链路中使用 MAC 地址传输数据帧,此时的一跳指的是源 MAC 地址到目标 MAC 地址之间传输帧的区间。也就是说它是主机或路由器网卡不经其它路由器而能直接到达相邻主机或路由器网卡之间的一个区间。
为了将数据包发送给目标主机,所有主机和路由器都维护着一张路由控制表,该表记录 IP 数据在下一步应该发给哪个路由器,IP 数据包将根据这个路由表在各个数据链路上传输。
该路由控制表有两种生成方式,一种是管理员手动设置,一种是路由器根据与其他路由器相互交换信息时自动刷新。前者叫静态路由控制,后者叫动态路由控制。为了让动态路由及时刷新路由控制表,在网络上互连的路由器之间必须设置好路由协议,保证正常读取路由控制信息(关于路由协议后面我们会单独介绍)。
路由控制流程
我们在上一篇介绍的 IP 地址的网络地址部分将会用于路由控制,根据网络标识选择下一跳的路由器。具体的跳转逻辑如下图所示:
要从源主机 10.1.1.30
发送一个数据包到目标主机 10.1.2.10
,由于 10.1.2.10
的网络地址与源主机 10.1.1.0/24
的网络地址不匹配,所以数据包被转发到路由器,路由器的路由控制表中如果已经存在 10.1.2.0/24
的网络地址映射,则直接将请求转发到对应的路由器(关于路由控制表的生成逻辑我们后面会详细介绍),如果目标主机 IP 地址在该路由器所在的数据链路中,再将数据包发送过去,就完成了将数据包发送到目标主机的流程。
IP数据包的分片与合并
IP 数据包是在数据链路层处理的基础上对数据进行打包,不同数据链路的各自最大传输单位(MTU)不尽相同,但是 IP 协议又是可以实现多个数据链路之间通信的协议,所以,意味着它对不同的数据链路差异进行了抽象,使得上层无需关注底层网络构造细节。
在具体实现时,IP 协议采用了对数据包进行分片处理,将较大的 IP 包分割成较小的包,到了接收端以后再根据分片序号重新组合起来传递给上一层,通过这种方式实现了对数据链路层的抽象。
分片会导致路由器处理负荷加重,所以只要允许,都不会让路由器进行 IP 数据包的分片处理,其次,在分片过程中,如果某个分片丢失,整个 IP 数据包都会作废。实际实现过程中,为了避免路由器对 IP 数据包进行分片,还产生了一种叫做「路径 MTU 发现」的技术,所谓路径 MTU 指的是从发送端主机到接收端主机之间路由器不需要对 IP 数据包进行分片的最大 MTU 的大小,然后发送端根据这个 MTU 的大小对数据包进行分片发送,从而避免路由器对其进行分片处理。感兴趣的同学可以去了解下其实现细节,这里就不深入展开了。
IP 报文头格式
有了前面介绍的 IP 地址和路由控制基础理论,继续来看下 IP 报文首部(有的地方称之为报文头)的格式,看看前面介绍的原理如何落实到具体的数据结构上。
我们整个网络协议分享还是以 IPv4 为主,所以我们主要来看下 IPv4 报文首部的格式。
通过 IP 协议进行网络通信时,需要在数据前面加上 IP 首部信息(有的地方称之为 IP 头,一个意思),IP 首部中包含着基于 IP 协议进行发包控制时所有的必要信息:
下面我们看具体看下每个字段表示的含义:
- 版本:用于标识 IP 首部的版本号,IPv4 的版本号即4,关于 IP 首部的版本信息可以参考这里:https://www.iana.org/assignments/version-numbers/version-numbers.xhtml。
- 首部长度:IP首部的大小,单位为4字节。
- 区分服务(TOS):用来表示服务质量,IP 协议本身是一种尽力服务的协议,无法保证通信质量,但是近年来随着音视频服务对实时性要求的提高,在使用 IP 通信过程当中保证服务质量的技术也有了蓬勃发展。DSCP 字段用于在通过 DiffServ 控制网络质量的时候设置包的优先级;ECN 则主要用于网络通信中的显式拥塞通知。
- 总长度:IP首部与数据部分结合起来的总字节数,最大长度是65535。
- 标识:用于 IP 包分片重组,不同分片标识值不同。
- 标志:表示包被分片的相关信息。
- 片偏移:用来标识被分片的每一个分段相对于原始数据的位置。以上三个字段用于 IP 包的分片与重组。
- 生存时间:最初设计为网络包的有效时间,实际用于可以中转多少个路由器,每经过一个路由器,TTL值减1,直到为0则丢弃该包。
- 协议:标识 IP 首部的上一层首部隶属于哪个协议,比如 TCP 或 UDP,具体支持的协议信息请参考这里:https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml。
- 首部校验和:只校验数据报的首部,不校验数据部分,主要用来确保 IP 数据报不被破坏。
- 源地址:发送端 IP 地址。
- 目标地址:接收端 IP 地址。
- 可选项:通常在实验或诊断时才使用。
- 填充:在有可选项的情况下,首部长度可能不是32位的整数倍,通过向该字段填充0,将其调整为32位整数倍,以方便计算机进行处理。
- 数据:传输的具体数据(并不是首部的一部分)。
感兴趣的话,可以试试通过 WireShark 对网络请求进行抓包,就可以看到对应的 IP 首部信息了:
可以看到,和我们上面介绍的 IP 头格式完全一致,只是没有可选字段和填充项。
在实际通信中,仅凭 IP 协议还不够,还要借助众多支持 IP 协议的相关技术才能更好地实现最终通信。
IP 地址是如何自动分配的
前面我们介绍了 IP 地址,那么我们的 IP 地址是怎么分配的呢?
DHCP 的引入
我们已经知道 IP 地址分为公网 IP 和私有 IP,公网 IP 一般由运营商维护和分配,而私有 IP 是局域网内部的 IP,是需要局域网内部去管理和维护的,当然,我们可以按照所属网段自己去设置,如果是在家里只有几台联网设备还好,如果是在学校或公司,动辄上百台机器,如果由 IT 管理员去设置每台机器的 IP 地址,不仅繁琐,而且容易出现 IP 地址冲突。并且按照我们现有的经验来看,不管是在家里、学校还是公司,都不需要手动设置 IP 地址,而是插上网线(台式机),或者接入 WiFi(手机或笔记本电脑),就可以上网了,IP 地址由系统自动帮我们分配。
这里面用到了自动分配 IP 地址的协议,也就是动态主机配置协议,简称 DHCP,不管是在 Windows 还是 Mac 中都可以看到它的身影:
有了 DHCP,计算机或者智能手机只要连上网络,就能实现 TCP/IP 通信,从而实现了 IP 地址的自动分配和统一管理。
DHCP的工作原理
使用 DHCP 之前,需要先在局域网内假设一台 DHCP 服务器(一般由路由器充当),然后将 DHCP 所要分配的 IP 地址设置到服务器上,此外,还需要将子网掩码、路由控制、DNS 服务器地址等信息也设置到服务器上。
新加入的机器或设备(DHCP 客户端)使用 IP 地址 0.0.0.0
(此时还没有分配IP地址)发送了一个广播包,目标 IP 地址为 255.255.255.255
(广播地址)。广播包里包含了该机器的 MAC 地址,请求 DHCP 服务器为其分配 IP 地址。
DHCP 服务器收到广播后会通知新加入机器可用的网络设置(通过 MAC 地址唯一确定),包括 IP 地址、子网掩码、网关等信息,这个通知仍然以广播形式发送,因为这个时候新机器还没有分配 IP 地址。此时,DHCP 就已经将这个 IP 地址标记为已分配,其它机器将无法获取到这个 IP。
新机器拿到 IP 地址后,会给 DHCP 服务器发送一个 DHCP 请求,表示接受这个 DHCP 服务器分配的 IP 地址,此时还是使用广播包,DHCP 服务器收到请求后,会返回给新机器一个 DHCP ACK 消息包,新机器收到消息后,由操作系统完成 IP 地址分配。
当新机器离开这个网段时,会发送 DHCP 解除包让这个 IP 地址回到 DHCP IP 地址池,以便其他新接入设备使用。
注:之所以分成两个阶段,是因为当有多台 DHCP 服务器时,新机器只会选中其中一个服务器分配的 IP 地址,一般是最先到达的那个,客户端发起第二次广播请求,还会告知其他服务器,我已经选择了某一台 DHCP 服务器分配的地址,其他服务器分配的 IP 地址可以回收给其他客户端使用。
一般在家里,大多只有一个以太网/无线局域网网段,连接的机器和设备不多,一台 DHCP 服务器(路由器)就够了。而对于学校或公司来说,可能存在多个网段,如果针对每个网段都设置一台 DHCP 服务器管理和维护起来比较麻烦,这个时候,我们可以借助 DHCP 中继代理对 DHCP 进行统一管理,我们还是假设一台 DHCP 服务器,子网网段上的服务器使用 DHCP 中继代理来替代,DHCP 客户端会向 DHCP 中继代理发送 DHCP 请求包,而 DHCP 中继代理在收到这个广播包后再以单播的形式发送给 DHCP 服务器,服务器收到这个包以后再向 DHCP 中继代理返回应答,并由 DHCP 中继代理将此包转发给 DHCP 客户端。
域名与 IP 地址是如何映射的
DNS 的引入
根据前面的介绍,通过 IP 地址就可以实现主机之间的连接和通信,对机器来说这没有什么问题,但是对于使用网络的人来说,尤其是普通用户,如果需要输入一串莫名其妙的 IP 地址才能访问对方主机,不仅麻烦,而且难以记忆,因此,就诞生了 DNS。
DNS 是英文名 Domain Name System 的缩写,顾名思义,它是域名管理系统,专门用于将域名解析为对应的 IP 地址。这样一来,我们只需要输入网站的域名,如 laravelacademy.org
,底层 DNS 就会帮我们检索与之映射的 IP 地址,拿着这个 IP 地址就可以访问对方主机了,这也是日常我们上网的正常操作方式。
DNS 的前身
在 DNS 诞生之前,为了解决主机与 IP 地址的映射,会为每个主机设置一个主机识别码,或者叫主机名,在网络通信时可以直接使用主机名而不是 IP 地址,通过主机名访问对端主机时,底层也会将其转化为对应 IP 地址,而实现这一映射功能的解决方案就是在每个主机存储一个 hosts
文件:
在互联网诞生的混沌之初,为了实现与外部网络的连接,互联网信息中心会统一管理一份 hosts
文件,如果网络中新增一台机器或更新已有机器的 IP 地址,需要更新中心的这份 hosts
文件,并且其它计算机要经常定期从中心下载最新的 hosts
文件才能保证网络的畅通。
显然这种方式无法应对日益扩大的网络规模,尤其是现在这种数十亿乃至百亿台设备连接到网络的场景,但是这种方式也没有完全从我们的视野中消失,在局域网内部或者用于测试的本地机器,我们还在使用 hosts
文件存放虚拟域名,以方便本地的开发测试:
127.0.0.1 localhost
255.255.255.255 broadcasthost
127.0.0.1 laravel.test
在浏览器中输入域名发起访问后,系统会先从 hosts
文件中读取记录,如果输入的域名在 hosts
里面做了映射,则直接拿到对应的 IP 地址发起请求,如果没有的话才会启用 DNS 做域名映射。
DNS 服务器
在介绍 DNS 服务器之前,我们先来看看域名的组成结构。
以 Laravel 学院为例,域名是 laravelacademy.org
,其中 laravelacademy
表示 Laravel 学院的固有域名,org 表示顶级域名,固有域名和顶级域名通过.
分隔,有的网站还细分出二级域名,比如腾讯视频的网站是 v.qq.com
,我们可以将 v
称作二级域名。
注:域名一般通过在域名服务商那里注册获取,然后域名与 IP 地址的映射也是在域名服务商那里完成。映射之后,就可以通过域名与对应的主机通信了。
DNS 服务器指的是管理域名的主机或软件,它可以管理所在分层的域名信息:
- 根 DNS 服务器:返回顶级域 DNS 服务器的 IP 地址
- 顶级域 DNS 服务器:返回权威 DNS 服务器的 IP 地址
- 权威 DNS 服务器:返回固有域名对应主机的 IP 地址
每一个分层都设有 DNS 服务器,各层 DNS 服务器都了解该层以下分层中所有 DNS 服务器的 IP 地址,所有 DNS 服务器又都了解根 DNS 服务器的 IP 地址,以便在当前分层找不到映射的 IP 地址时,跳转到根 DNS 服务器从上往下继续查找。
进行 DNS 查询的主机或软件叫做 DNS 解析器,用户所使用的计算机或工作站就属于解析器,一个解析器至少需要注册一个以上 DNS 服务器的 IP 地址,通常,它至少包括组织内部的本地 DNS 服务器的 IP 地址:
DNS 查询原理
以下是一个 DNS 查询流程图:
- 用户在浏览器中输入 www.baidu.com 访问百度首页,计算机会先从本地 hosts 文件或 DNS 缓存解析器中查询有无相应的 IP 地址映射记录,如果有的话直接返回,否则进入下一步;
- 将域名发给本地 DNS 服务器(通过 DHCP 配置,一般由宽带运营商自动分配)进行查询,如果缓存中有记录则返回对应 IP 地址,否则进入下一步;
- 将域名发给根 DNS 服务器进行查询,根 DNS 服务器不会直接解析域名,但是会返回查询域名对应顶级域名 DNS 服务器的 IP 地址,比如这里是 .com;
- 然后本地 DNS 服务器会到 .com 顶级域名服务器查询,顶级域 DNS 服务器会根据查询域名返回 baidu.com 对应的权威 DNS 服务器的 IP 地址;
- 接下来,本地 DNS 服务器根据返回的权威 DNS 服务器的 IP 地址去对应的服务器(域名解析出处)进行查询,这一次就可以获取到 www.baidu.com 域名对应的 IP 地址了,拿到这个 IP 地址,就可以将其返回给对应的计算机。
上述流程走下来,还是很费劲的,所以不管是 DNS 解析器还是 DNS 服务器,都会将最新了解到的信息暂时缓存起来,这样,可以减少每次查询时的性能消耗。
好了,这样下来,你应该对域名与 IP 地址之间是如何映射的很清楚了吧。
IP 地址与 MAC 地址是如何映射的
ARP 的引入
通过前面的介绍,我们已经知道在计算机网络中,只要确定了 IP 地址就可以向目标主机发送 IP 数据包。不过,在数据链路底层进行通信时,却有必要了解每个 IP 地址对应的 MAC 地址。这样才能完成「最后一公里」的通信,把数据包发送给目标主机。
而通过 IP 地址获取 MAC 地址就需要借助 ARP,ARP 是一种地址解析协议,以目标 IP 地址为条件,来定位下一个应该接收数据包的网络设备的 MAC 地址,如果对应 MAC 地址不存在,意味着目标主机不在该网段内,接着通过 ARP 查找下一跳路由器的 MAC 地址。
ARP 的工作原理
ARP 协议借助 ARP 请求和响应两种类型的包来确定 MAC 地址,以下是 ARP 请求和响应的一般流程:
主机 A 为了获取主机 B 的 MAC 地址,首先要通过广播发送一个 ARP 请求包,这个包中包含了想要了解其 MAC 地址的对应主机 IP 地址(即主机 B 的 IP 地址),由于广播包可以被同一链路上的所有主机或路由器接收,因此 ARP 的请求包就会被这个链路上的所有主机和路由器进行解析,如果 ARP 请求包中的目标 IP 地址与自己的 IP 地址一致,这个节点就将自己的 MAC 地址塞入 ARP 响应包返回给主机 A。有了 IP 地址和 MAC 地址,就可以完成链路内的 IP 通信。
为了降低网络流量,提高通信效率,发送 ARP 请求包的主机会把获取到的 MAC 地址缓存一段时间,IP 地址与 MAC 地址映射关系表叫 ARP 缓存表,每执行一次 ARP,对应的缓存表内容就会被清除。
反之,接收 ARP 请求的那个主机又可以从这个 ARP 请求包获取发送端主机及其 MAC 地址,这时候,它也可以将这些 MAC 地址信息缓存起来,从而根据 MAC 地址发送 ARP 响应包给发送端主机。
IP 地址与 MAC 地址对比
整个互联网其实就是通过路由器将一个个网段连接起来,同一个网段(链路)内通过 MAC 地址即可通信,但是跨网段的通信需要通过 IP 地址,如果没有 IP 地址,仅仅通过 MAC 地址无法知道节点所处的位置(没有网络地址部分),就需要向全网发送数据包,可想而知这将会造成多大的网络流量,而且维护这个 MAC 地址的缓存表也非常庞大。
所以,在互联网通信中,IP 地址和 MAC 地址缺一不可,于是就有了将这两个地址相关联的 ARP 协议。另外,有些时候我们可能还需要反过来通过 MAC 地址获取 IP 地址,相应的协议是 RARP。
下面是一个跨网段的网络请求根据 IP 地址和 MAC 地址最终到达目标主机的流程图:
如上所述,在整个过程中,IP 头没有变动,而数据链路帧头(MAC头)里的目标 MAC 地址随着链路的变动而变动,从而将网络包一步步转发到目标主机,完成整个通信。
聊聊 ping 和 traceroute 的底层工作原理
ping 与 ICMP
日常工作中,我们在测试是否可以连接到某个域名或 IP 时,通常会使用 ping
命令:
ping
是基于 ICMP 进行工作的,ICMP 全称 Internet Control Message Protocol,意为互联网控制报文协议。
ICMP 的主要功能包括,确认 IP 包是否成功送到目标地址,通知在发送过程中 IP 包被废弃的具体原因,改善网络设置等。
在网络通信中如果某个 IP 包因为某种原因未能到达目标地址,那么这个具体的原因将由 ICMP 负责通知。ICMP 这种通知报文会使用 IP 进行发送,ICMP 报文也是封装在 IP 包里面的。
ICMP 报文类型
ICMP 报文大致分为两类:一类是通知出错原因的错误消息(差错报文),另一类是用于诊断的查询消息(查询报文)。所有的报文类型如下:
其中最常见的就是类型 8
和 0
,两者都是回送消息,用于进行通信的主机和路由器之间,判断所发送的数据包是否已经成功到达对端,可以向对端主机发送回送请求消息(类型 8
),也可以接收对端主机发回来的回送应答消息(类型 0
),常用的 ping 命令就是利用这个消息实现的。
ping 工作原理
ping
命令执行的时候,源主机首先会构建一个 ICMP 请求数据包,ICMP 数据包内包含多个字段。最重要的是两个,第一个是类型字段,对于请求数据包而言该字段为 ``8;另外一个是顺序号,主要用于区分连续 ping
的时候发出的多个数据包。每发出一个请求数据包,顺序号会自动加 1
。
然后,由 ICMP 协议将这个数据包连同地址 220.181.57.216
一起交给 IP 层。IP 层将以 220.181.57.216
作为目的地址,本机 IP 地址作为源地址,加上一些其他控制信息,构建一个 IP 数据包。
接下来,需要加入 MAC 头,最后将它们传送出去。
主机 B 收到数据帧后,先检查它的目的 MAC 地址,并和本机的 MAC 地址对比,如符合,则接收,否则就丢弃。接收后检查该数据帧,将 IP 数据包从帧中提取出来,交给本机的 IP 层。同样,IP 层检查后,将有用的信息提取后交给 ICMP 协议。
主机 B 会构建一个 ICMP 应答包,应答数据包的类型字段为 0
,顺序号为接收到的请求数据包中的顺序号,然后再发送出去给主机 A。
在规定的时候间内,源主机如果没有接到 ICMP 的应答包,则说明目标主机不可达(类型 3
);如果接收到了 ICMP 应答包,则说明目标主机可达。
为了安全起见,某些机器和设备是禁止被 ping 的,所以,ping 不通并不意味着一定是网络不通,对于禁止 ping
命令的主机,需要通过 telnet
命令测试是否可以连接。
通过 traceroute 诊断网络
前面提到的 ping
使用的是 ICMP 的查询报文,下面我们再来介绍一个使用 ICMP 差错报文的工具 —— traceroute
。
前面我们介绍过,IP 包中有一个字段叫 TTL
,它的值随着每经过一个路由器减 1,直到为 0 时该 IP 包被丢弃。此时 IP 路由器会发送一个 ICMP 超时消息给发送端主机,并通知该包已丢弃。
traceroute
正是基于这一原理,它的参数指向某个目的 IP 地址,它会发送一个 UDP 的数据包。将 TTL
设置成 1
,也就是说一旦遇到一个路由器或者一个关卡,就表示它“牺牲”了,于是,返回一个 ICMP 包,也就是网络差错包,类型是时间超时。接下来,将 TTL
设置为 2
。如此反复,直到到达目的主机。这样,就拿到了所有的路由器 IP(不显示指定 TTL
默认返回所有中间路由器 IP):
注:中间某一跳路由器不返回 IP 地址而是 ***,说明在这一跳的路由器设置了不应答 ICMP。
在网络发生问题时,traceroute
是一个强大的诊断工具。
如何通过 NAT 技术实现公网 IP 与私有 IP 地址间的转换
为了解决 IPv4 地址即将枯竭的问题,会在本地网络使用私有 IP 地址,然后在连接互联网时使用 NAT 技术将其转化为公网 IP 地址(全局 IP 地址),那么,NAT 技术是如何实现这个转化的呢?
下面我们来看一张图:
在 NAT 路由器(即本地网络与外部网络连接的路由器)内部有一张自动生成的用来转换地址的表,当 10.0.0.10
(私有IP) 向 163.221.120.9
(公网IP) 发送第一个包时生成这张表,并按照表中的映射关系进行处理。
当私有网络内的多台机器同时都要与外部通信进行通信时,仅仅转换 IP 地址,人们不免担心公网 IP 地址是否够用,这时采用包含端口号一起转换的方式可以解决这个问题:
即在通过 NAT 路由器做 IP 地址转化时将本地网络中不同主机转化为同一个 IP 地址,而将端口号转化为不同端口号,以示区别。
这里需要注意的是,在使用 TCP 或 UDP 的通信中,只有当目标地址、源地址、目标端口、源端口以及协议类型(TCP或UDP)五项内容都一致时才被认为是同一个通信连接。