2.3 分层架构
有了大致的思路之后,让我们来想一想如何在数据链路的基础上构建一个完整的网络体系。
上一节中我们讲解了如何构建可靠的数据链路。虽然这个数据链路是我们附加在物理链路之上的抽象概念,但这种数据链路我们一般都会使用纯硬件实现。但是如果想仿照数据链路使用硬件实现接下来的功能,就不是那么简单了。
例如,接下来要实现数据的转发功能。但是问题是,我们如何知道要将数据转发到何处呢?直接将整个网络的拓扑结构存储在每个机器节点里吗?如果是这样,当机器节点增加时需要将网络中的所有机器节点数据全部更新一遍,这无疑是费时费力的(比如像图2-3那样)。那么我们就需要实现一种复杂的自学习式的寻路算法,如果直接使用电路实现成本极高。同时我们还要确保数据可以可靠地被转发到目的机器节点,如果数据在路途中丢失或损坏我们也要采取一定的措施。此外,如果软件直接使用硬件接口,手动将数据划分为一个个分组进行传送,无疑会加大应用软件的开发成本。
换言之,想要构建一条纯硬件的、任意机器节点之间可靠传输的数据链路成本太高。应该如何解决这些问题呢?
在计算机的世界中,我们将这种问题称为“高复杂性”问题,而解决高复杂性问题一种惯性思维就是加入中间层。
例如,我们可以将物理链路看成一个层,而数据链路看成另一个层,如图2-4所示。
图2-4 2层模型
图2-4中上面一层称为数据链路层,下面一层称为物理层。通过之前的讲解,可以看到我们完全是在物理层的基础上实现了一个数据链路层,保证相邻机器节点之间的可靠数据通道。那如果我们在数据链路层的基础上再加一个层,这个层假设相邻机器节点之间有可靠且可分数复用的数据通道,而该层只考虑在这种可靠的数据通道中实现节点的分组转发功能,并使用软件技术实现这种算法,是不是可以降低整个系统的复杂度呢?
实际上就是如此。
所以我们就在这上面再加一层,称之为网络层(就是在网络中寻找目标机器节点),该层主要使用软件实现,如图2-5所示。
图2-5 3层网络模型
但现在又出现新的问题——同一个机器节点上可能会运行不同的软件程序,如果A机器节点的程序1向B机器节点的程序2发送数据,A机器节点的程序3也会向B机器节点的程序4发送数据,那么B机器节点接收到数据时该如何区分呢?此外,网络层依然是分组传送,如果直接让软件自己手动对数据进行分组开发成本过高,如果可以将数据传输看成无限字节流的传输就太好了。但直接在“寻找路径”这一层实现这些功能又势必会增加软件的复杂度。
所以我们故技重施,再加一层,用这一层实现端到端(也就是应用程序之间的)的字节流数据传输通道,我们称之为传输层。目前的分层结构如图2-6所示。
图2-6 4层网络模型
最后,虽然所有的应用程序都可以将数据转换为字节流,但普通的字节流是毫无意义的,为了让字节流变得有意义,需要双方遵守同样的规则来理解一个字节流,也就是双方要有一个软件层的解释字节流的协议。很明显传输层并不负责这件事情,而且由于应用程序类型众多,传输层如果还要考虑解释字节流,负担就太重了。因此我们还需要再加一层,不同的应用程序在这一层上建立自己的协议,由于这一层完全是面向应用程序的,因此我们称之为应用层。
现在的层次结构如图2-7所示。
图2-7 5层网络模型
到现在我们终于可以松口气了,你会发现,我们已经一步步将整个分布式网络的架构构建出来了。
我们可以看出,在解决这个问题的过程中,为了保证网络的简单性,我们根据实际问题将整个网络划分成了多个逻辑层次,每个层次专注解决一个或几个相关问题。这样一来每个层次都可以直接使用下一层次提供的“服务”,降低了每个层次的复杂性,进一步降低整个网络构建的成本。
幸运的是,经过实践打磨出的TCP/IP协议正采用了这种分层的思想,TCP/IP的分层结构如图2-8所示。
图2-8 TCP/IP协议栈
提示 Request For Comments(RFC)是一系列以编号排定的文件。文件收集了有关互联网的信息,以及UNIX和互联网社区的软件文件。目前RFC文件由Internet Society(ISOC)赞助发行。基本的互联网通信协议在RFC文件内都有详细说明。对这些概念感兴趣的读者可以访问http://www.ietf.org/rfc.html了解详细信息。
其中物理层在协议之外。而数据链路层和我们的一样,保证相邻通信节点之间的可靠数据传递。网络层负责网络之间任意两点数据包的传送。传输层负责端到端的字节流抽象。最后应用层负责构建应用程序协议。
接下来具体介绍如何构建数据链路层上的每一层,并引入TCP/IP的一些规范。