网际协议IP知识总结
================

## 知识脉络

网际层的主要工作是实现数据在异构网络之间的传输，即处于两个不同的网络中的主机的通信。对于要发送数据的主机而言，最重要的任务是如何定位它想要与之通信的主机，即`路由选择`的问题。网际层的所有内容几乎都是围绕`路由选择`而展开，具体说来又分为两部分，即网际结构（我自己定义的词语）和路由选择协议。

因特网是一个庞大的网络，其中含有亿万计的节点，并且整个网络还处于动态变化当中——随时都有主机接入接出，也随时都有路由器发生故障。在这样的网络中找到数据传输的最短路径，显然是不能通过常规的图算法来做的，这里的基本思想在于`层次化`，把大网络拆分成小网络，然后再对小网络小网络进行拆分，形成一个树形结构。

层次化第一条，进行网络的划分。将IP地址拆分成了`网络号: 主机号`，即传统的A, B, C类网络。在同一个网络中的主机，往往在地理位置上也接近，它们拥有相同的网络号，这样在数据传输时，所有数据都是首先传输到该网络，再由该网络的路由器进行分发；在进行路由选择时，所有在一个网络内的主机，使用同一个网络号作为它们的标识，以B类网络为例，一个B类网络中最多的65534台主机使用了同一个路由表项，大大减小了路由表的大小。

层次化第二条，构造子网。以A类网络为例，一个A类网络内最多拥有`2^24 - 2`台主机，数据分发到该网络后，定位合适的主机也是一个复杂的问题。因此可以对网络进行进一步的划分，形成网络的树形结构，数据首先传输到层次更高的路由器，再一级一级地向叶节点方向转发。

层次化第三条，路由聚合，即构造超网。对于不同的网络，尽管它们的网络号不同，却具有相同的网络号前缀，在进行路由转发时，这些网络都是从同一个端口转发。这样就可以把这些不同的网络，在逻辑上组成一个更大的网络（网络号即是它们的前缀），路由表只需要存储这个更大的网络的转发表项，可以减小路由表的大小。

层次化第四条，自治系统与自治区域。将一个区域的许许多多不同的网络，构成一个自治系统，往往是一个国家或者行政区，自治系统具有一些`边界路由器`，负责与其他自治系统的通信——所有传输到该自治系统的数据，都首先传输到`边界路由器`，再由`边界路由器`进行转发。同理，自治系统内部还可以划分自治区域，进一步实现层次化。

层次化第五条，本地地址与全球地址。由于IP地址的消耗，无法做到每台主机都拥有一个全球IP地址，实际上，一般的主机上网，都是使用本地地址，本地地址必须要转换成全球地址才能进行通信，这个转化过程是通过网络地址转换(NAT, Network Address Translation)来实现的。这样，连接到一个路由器的主机，都获得一个本地地址，然后统一使用路由器的全球地址接入到互联网，在这种情况下，就相当于32位IP地址都成为了网络地址，将IP地址进一步层次化了。还有一个好处就是缓解了IP地址的消耗。

上面的内容都是在讨论因特网的网际结构的问题，搭建好了结构，还需要在这样的结构上实现一定的路由选择算法。这样涉及到的算法有`路由信息协议`(RIP, Routing Information Protocal)，`开放最短路径优先`(OSPF, Open Shortest Path First)，还有外部网关协议`边界网关协议`(BGP, Border Gate Protocal)，内容都比较简单，就不再赘述了。

此外，IP层还涉及到一些概念，一些细节，在这里没有涉及。包括IP数据报的头部结构，ICMP以及它的两个典型应用场合(ping, traceroute)还有IP组播以及虚拟专用网络(VPN)等概念。

## 网际层提供的功能

从结论来说，网际层向运输层提供的是无连接的服务。网际层负责将数据从一台主机，传输到连接到网络的另一台主机。

为什么不像传统_电信网_一样，提供面向连接的服务？

电信网是需要两个用户首先建立连接，然后才能进行通信，所以是一种可靠的传输。可是计算机之间的通信与电话机的通信有本质的区别--计算机具有强大的差错处理能力，而这时电话机所不具有的。所以网际层的传输可以尽量简单灵活，尽最大努力交付，而把可靠传输的工作留给上面的运输层。

## 产生的一些思考

上面说，网际层的工作是实现数据在主机之间的传输，那么这究竟意味着什么？完成这点又需要哪些工作呢？

首先，为了把数据传输到另一台主机，当前的主机需要知道另一台主机的位置。这意味着:

+ 网络中的每台主机都要有一个独一无二的id，一个不会重复的地址
+ 当前主机需要有办法从茫茫人海(机海？)中标志出目标主机
+ 传输过程当中，需要有一些信息中转站(数据链路层)，否则信道的利用率会相当低

第一条是容易理解的，因为如果主机地址不能被唯一标志的话，很有可能数据会被传输到别的主机上去，会有信息泄露之类的问题。实际上，每一台主机的网卡都有唯一确定的硬件地址(MAC地址)，是由网卡生产商决定的。

第二条是基于下面的理由。如果我只想和唯一的一台主机通信，问题也不是那么简单，因为主机的位置是会发生变化的，所以每次我可能都会需要一条不同的通信链路，如何找到这条最佳的链路是一个问题。另外，实际情况是，对于互联网中每一台主机，理论上都可以相互通信，这样每个主机都需要管理所有其他主机的地址，而这是不可能的，因为我们有数百亿个主机，以后还可能会更多。

第三条详见数据链路层与物理层协议。

这样的话，主机之间通信的步骤应该是下面这样:

+ 主机A需要和主机B通信，A知道B的唯一标志地址
+ 主机A查询到B的路径(需要经过哪些信息中转站)，然后向第一个中转站发送信息
+ 信息在各个中转站之间传递，直到信息发送到主机B

从上述过程可见，网际层传输最核心的工作就是获得到另一台主机的路径问题，或是大规模网络单源最短路径问题。下面的讨论都是基于路径选择而展开。

## 使用IP地址

首先指出结论，要在百亿级的主机中找到目的主机，使用硬件地址是不可能的，而需要使用逻辑地址。

上述结论是基于以下考虑:

+ 数据的传输是与地域有关的，当前主机与同一地域的不同主机通信，极有可能是使用相似或是相同的路径。因此，如果给处于相近地域的主机划分一个共同的<上一级地址>，数据传输时先传输到<上一级地址>，再在组间传输，需要管理的地址数量会大幅度减小
+ 不能直接使用硬件地址，因为硬件地址是与地域无关的，只与网卡生产的厂家有关。

所以，我们需要在硬件地址之上抽象出一层逻辑地址，并且该逻辑地址是与地域相关的，共同地域的一些主机享有相同的逻辑地址头部，就好像楼层与房间的划分关系一样。实际上，这是树形结构的思想。

而IP地址，就是这里使用的逻辑地址。

### 分类的IP地址

如上面所述，IP地址的结构是<网络地址：主机地址>，一共含32位。根据网络地址的头部，又可以划分为几类IP地址

+ A类地址：网络号8位，首部为零。主机号占24位
+ B类地址：网络号16位，首部为10。主机号占16位
+ C类地址：网络号24位，首部为110，主机号占8位
+ D类地址：多播地址
+ E类地址：保留

此外，还有一些特殊的IP地址。

+ 网络号为`0111 1111`的A类地址,保留为本地环回测试，用于本主机的进程之间通信之用
+ 网络号全零：表示本网络
+ B类和C类的固定位以外，全零的网络号都是不指派的：`128.0.0.0` 以及 `192.0.0.0`
+ 主机号全零表示本主机连接到的__当前网络地址__
+ 主机号全一表示当前网络的全部主机

### IP地址实现树形结构

那么问题来了，IP地址是如何实现将多个同一地域主机归属到同一个地址呢？

使用IP地址后，连接到同一个网络的主机(通常是同一个地域，如局域网)都拥有同一个网络号。在数据传输的时候，路由器只是根据网络号来转发分组，从而一个网络的多台主机都使用同一个网络地址。需要存储的地址空间大幅减小了。

在数据到达本网络后，本网络的路由器只需存储了本网络主机的IP地址与映射的物理地址，就可以把数据发送给目的主机了

### 划分子网与构造超网

上面的解决方案看起来已经很好了，只是在IP地址方面，似乎还存在一些问题。

IP地址分为A,B,C三类网络，可是这三类网络主机的划分却是很不均匀的。如A类网络，每个网络可以有2^24-2台主机(24位主机号，除去全零和全一),可是C类网络最多只能有254台主机。

这会产生一些问题：

+ 地址空间利用不足。如分配了A类地址的网络，往往不能完全用完所有的IP地址。
+ 对于A类地址的网络，即使是通过网络号找到了目的网络，在其网络内部定位到目的主机仍然是一个不小的工作，因为A类网络最多可以拥有一千多万台主机，需要管理这么多主机的地址并不是一件轻松的工作。
+ C类地址的网络还是太小了，世界上可以存在大量C类地址网络，在这些网络中定位到目的网络也非常困难，需要管理大量的网络地址信息。

对于前两个问题，可以通过构造子网解决。最后一个问题，可以通过构造超网解决。但实际上，构造子网与超网本质上是同一个思想。

我们先看IP地址的设计。IP地址分为了多种类型，这些类型的网络号是具有唯一前缀的。就是说通过网络号前缀，就可以知道这是哪一类IP地址，从而知道其网络号与主机号分别占多少位。

所以，如果我们增加一个变量表示网络号的位数，那么理论上我们是不是就可以拥有任意位数的网络号与主机号。这个变量就是子网掩码。如果该新的网络号位数大于原来的位数，这就是构造子网；如果该新的网络号囊括了多个原来的多个网络，这就是构造超网。

可以看到，通过上面的方案，IP地址的分类已经没有意义了。因此这种方法也叫无分类编址(CIDR, Classless Inter-Domain Routing, 或叫无分类域间路由选择)

当然，实际上并不能拥有所有位数的网络号，因为这样会导致一些网络太大，而另一些网络太小。实际上常用的网络号前缀长度包括/13 - /27

### 从IP地址到硬件地址的转换

当数据传输到目的主机所在网络的路由器后，该路由器需要将数据直接转发给目的主机。可以看到，这里已经不是网际层的工作范围了，因为这里的数据传输是网内传输。这一步的数据传输需要知道目的主机的硬件地址了，因此需要完成IP地址到硬件地址的转换。这这就要用到地址解析协议ARP。

ARP的功能就是从网际层使用的IP地址，解析出在数据链路层使用的硬件地址。所以，按照我的理解的话，这应该是一个数据链路层的协议。

ARP的实现主要需要一个ARP高速缓存，里面存放了本局域网上各主机和路由器的IP地址到硬件地址的映射表。局域网的每一台主机都管理有一个ARP高速缓存。

ARP高速缓存的构造流程如下：

+ 当前主机A需要发送信息给本局域网的另一台主机B,因此A查询自己的ARP高速缓存，如果查找到了B的硬件地址，则直接交付给B。若没有，则进入下一条
+ 主机A在本局域网上广播一个ARP请求分组，所有局域网上的本机都将受到这个请求
+ 主机B和请求分组中要查询的IP地址一致，因此主机B向A发送ARP响应分组，写入自己的硬件地址
+ A收到B的ARP响应分组后，在其ARP高速缓存写入主机B的IP地址到其硬件地址的映射。

### 网际层数据传输的流程

根据上面的讨论，可以归纳出网际层数据传输的流程

+ 主机A要向另一台主机B发送数据。主机A首先提取出主机B的IP地址，得出目的网络地址
+ 如果目的网络与当前网络是同一个网络，主机A查询主机B的硬件地址，并对B进行直接交付
+ 如果目的网络不是当前网络，则将数据包交付给合适的路由(特定主机路由或是默认路由)
+ 路由器查询其路由表，找到到达目的网络的下一个路由器，并且交付给下一路由器
+ 上述过程循环进行，直到交付给目的网络所在的路由器
+ 若没有找到路由，则报告转发分组出错

## 路由选择

根据上面的讨论，IP地址的抽象，子网与超网的划分，都是为了减少路由表中的条目，提升路由选择的效率。有了上面的基础，大概是可以归纳路由表具有哪些条目

### 路由表的条目

路由表并没有给出从一个网络到另一个网络的完整路径，而是给出了下一跳路由器。这样，通过不断地查询到达的路由表，最终还是可以将数据传输到目的网络。

路由表中的基本条目包括：
+ 目的网络地址
+ 子网掩码(网络掩码)：为了区分网络号和主机号
+ 下一跳地址

此外，还有一些字段根据路由选择算法的不同而异。

### 路由表的建立：路由选择算法

路由选择算法实际上是构造路由表的算法。

上面提到过，无分类编址的IP地址已经是为了减少路由表中的条目数，提高路由选择的效率。但在实际应用中，这样的无分类网络还是太多了，一个路由器不可能保存全部网络的路径。因此，按照和之前一样的思想，我们可以人为的再把这些网络做一些归类，这就是自治系统(Autonomous System)。

自治系统内部应该使用同一种路由选择算法。这也是产生自治系统的另外一个原因--许多网络会采用自己的路由选择协议，这样在路由选择时，由于前后会有多种不同的路由选择协议，很难得到一个全局比较优化的路径。因此可以把使用相同路由选择协议的网络划分成一个自治系统。一个自治系统对外表现出单一和一致的路由选择算法。

这样，路由选择协议就呈现出分层次的特征--在各个自治系统间会使用一种路由选择协议(外部网关协议EGP)，自治系统内部会各自采用自己的路由选择协议(内部网关协议IGP)。而自治系统对外的路由器会需要同时运行外部和内部的路由选择协议。

### 内部网关协议

类似于Dijkstra或是Floyd算法。总之就是在自治系统内部找到全局最短"路径"。不过这里的路径有不同的定义方式。

#### 路由信息协议RIP

RIP只使用路由器之间的距离(跳数)作为衡量路由选择的指标，尽管有时候路径更长的网络传输效率更高。

RIP协议的特点：
+ 每个路由器只与相邻路由器交换信息
+ 交换的信息是当前路由器的全部路由表
+ 按固定的时间间隔交换信息

各个路由器更新的原则就是找到到某个网络最短的路径。因此
+ 一个路由器受到相邻结点X发来的路由表。将其中的距离信息加一
+ 对于受到的路由表中的每一个项目，若本路由表中没有该目的网络，则添加到自己的路由表中
+ 若当前路由表中存在目的网络，且下一跳路由器是X，则用收到的项目替换当前项目(因为这是最新的消息，以最新的消息为准)
+ 若当前路由表中存在目的网络，但下一跳不是X，则比较距离，取距离更小的条目
+ 若三分钟还没有受到相邻路由器的信息，则把此路由器标记为不可达

存在的问题：好消息传播的快，坏消息传播慢

#### 开放最短路径优先OSPF

同样是三个要点

+ 每个路由器是向自治系统内的所有路由器发送信息。实现方法是每个路由器先发给自己相邻的路由器，相邻的路由器收到后再向自己相邻的进行转发。(洪泛法)
+ 发送的信息只是与本路由器相邻的路由器的链路状态(如是否连通，以及该链路的度量)。这个度量可以是距离，也可以是费用、带宽、时延。可以由自己定义，所以比较灵活。
+ 只有在链路状态发生变化时才进行更新。

与RIP相比的话，RIP中每个路由器只能知道到所有网络距离以及下一跳，而采用OSPF可以构造出全网的拓扑结构图(就跟Floyd算法似的)。然后说的是当网络较大时，OSPF可以更快收敛，运行性能更好，这是因为OSPF交换的信息仅仅是相邻路由器的连通状态，相比于RIP而言，信息量要小得多。

为了运行的更快，还可以在自治系统里面划分区域，洪泛法在各个区域内进行

### 外部网关协议BGP

边界网关协议BGP的目的并非是寻找到一条最优路由，而是力求寻找到一条能够到达目的网络的比较好的路由。这是由于各个自治系统运行各自的路由选择协议，对路径的度量不同。此外，还有一些自治系统会不允许某些自治系统通过，或是需要付费。因此找到全局最优路径非常困难。

采用路径向量路由选择协议

+ 各个自治系统的BGP发言人之间交换路由信息
+ 交换的信息是要到达某个网络所要经过的一系列自治系统(路径)
+ 每个自治系统可以构造出一个自治系统连通图，然后选择一条较好的路径

### 路由表的检索

使用二叉线索树进行检索。唯一前缀(大约是哈夫曼树那些东西)

### 路由器的结构

#### 路由选择部分

也叫做控制部分，核心部件是路由选择处理机。主要是运行路由选择算法，与其他路由器交换信息，然后构造路由表。并且需要不断地更新和维护路由表。

#### 分组转发部分

由三部分组成

+ 交换结构：根据路由表对分组进行处理(查表)
+ 输入端口
+ 输出端口
