在找路过程中所作用的信息,由两方面来维护:每个主机都维护有自身的路由表(windows下用 route print打印出当前的路由表)。由于一般主机上只有一个网卡,因此路由表都比较简单,包含一个环回接口(127.0.0.1)和当前使用的IP,如果连网卡也没有,那就只有环回地址了。对所有发往127.0.0.1,localhost的数据报都在发往链路层(常见的就是以太网驱动层)前,就转往IP输入表了。而对发往自身IP的数据在发到链路层后,链路层在检查到这个地址是自身后,再发往IP输入表。
对发往其他地址的数据报,选用的接口就是网卡,全部发到网卡上。默认路由也是这个接口。
如果安装了多张网卡,windows的服务器版可以开启路由转发功能,也就是可以当做路由器用。如果只装了一张网卡,也使用转发功能,而实际上还是“从哪里来,到哪里去”,根本就达不到“选路”的目的。
这样主机在收到一个数据报时,先检查是不是发给自己的。如果是,就是正常的通讯,直接处理。如果不是,就根据是否可以转发的选项(是否开启路由转发功能),来决定是直接丢弃数据报,还是从网络接口中找一个合适的转发出去。
如果决定转发,这时才真正涉及到“找路”。主机和路由器各自都有一个路由表。首先检查路由表里的指向主机的那些表项,看是不是有哪一个条目就是要发往的目的地址。如果找到了,直接发往这个主机。如果找不到,再查指向网络号的那些表项,看主机要发往的网络是不是已经有记录。如果找到了,就发往这个网络要经过的接口。如果这些都找不到,就把这个数据报发往默认路由,由默认路由去处理。通常默认路由的表项更多,有更多的信息能找到要发往的目的地。如果默认路由还找不到,就再发往它的默认路由,一直到顶层。顶层的核心路由器如果还找不到,那就表明这个数据报确实是找不到目的地了,路由器返回一个ICMP报文,告诉发送方主机“网络不可达”,或“主机不可达”。具体信息根据路由器来决定,不过收到“主机不可达”的居多。
这些说起来是比较烦的。想像一个生活中的例子:
我想坐火车到拉萨去,到杭州火车站去坐车。杭州没有直达的车次(在青藏线通车前,全国都没有:)),也就相当于它找不到主机“拉萨”,也不知道它属哪个铁路局(网络号),它把我送到中转站徐州(默认路由)。徐州站同样找不到,但它知道主机“拉萨”属西部,也许网络号“郑州局”知道,于是把我打发到了“郑州”。而郑州也没有直达的车,它再把我打发到更近一点的“西宁”。然后在西宁火车站,得知青藏线还没有全线通车,此路不通。于是告知我“主机不可达”,这拉萨去不成了。
在生活中我就只得再回到杭州老老实实地过日子了。而在网络上,发到“西宁”的数据报是不会再发回来的,路由器(火车站)只是简单地把“我”扔掉,然后告知杭州警方。
这样就是一个找路的过程。如果在最后终于找到了,当然皆大欢喜,然后就可以“握手言欢”,找到组织了。接下来的事就与路由无关了。
从这个过程可以看到路由表项的重要。如果路由表的信息很详细,每个主机都能找到,那么只要发往路由器,所有的数据报都能顺利到达,就像杭州站有发往全国各地的车。然而实际上这样的要求不现实。网络上的主机不可胜数,就像全国的火车站多如牛毛,要做到每个主机都有一个项目,要求路由器有极大的容量来存放这些记录,而在这庞大的路由表中查找条目的效率也成问题。于是现在的路由器构成层次结构,每一层的路由器保存局部的路由信息。对自己处理不了的数据报,发往默认的路由去处理,这样对单台路由器的要求可以降低一些。
然后就是路由信息的创建与更新问题了。主机的开机关机,路由器的开机关机,这些都是不可预知的,也就是说路由信息可能是不确定的,这一分钟这条路还是通的,下一分钟说不定就不通了(关机了,崩溃了,被攻击了。。。)。这样造成的路由信息失效需要及时更新,以免造成错误的路由。
路由基本信息的创建一般是在系统启动过程中完成,如默认路由的配置。用 route add 命令可以手动加入一个静态路由。更多的路由信息是在通信过程不断充实的,也就是路由器自己慢慢“学”到的。这个跟ARP有一点类似的地方。在局域网内,如果要发数据报到另一台主机,例如从A发到B。如果一开始A不知道B在哪里,就发一个ARP询问B在哪里。B收到后回答自己的MAC地址,然后ARP守护程序会把这个MAC与B机的IP组合成一项保存起来。下次有数据要发到B时,就不用再问了,直接发到对应的MAC地址(用arp -a 可以查到当前的arp表项)。路由器也类似,如果它知道有一个接口可以发送,就把这个接口保存起来。不同的是,ARP工作在链路层,在IP层以下,而路由器处理起这些信息来,比ARP守护程序要复杂得多。
本文来源:天极yesky 作者:佚名