以下的东西是小弟以前计算机网络实验作业的一部分,觉得有点保留的价值,就拿过来了。实验的目的是检验两主机是否能ping通。
如果仅仅是简单的把ping的结果记录下来,然后按照结果去推为什么这样可以ping通,那样不行的话,根本就达不到了解两台主机互相ping的实质。所以我决定先用理论严格的TCP/IP协议规定的步骤进行电脑似的傻瓜推导,然后再用实验结果实际检验正确与否的方法。这种方法看起来似乎不难,实际操作的时候却遇到了很多的阻力。
事实上,关于这方面的文章可以说相当的多,但除非你看了源代码,很难按照那种笨笨的傻瓜方式一步一步推导下来。网络上的文章讲得似是而非,可能这涉及一点,那涉及一点,并不十分系统。在看了大量的文章跟论坛之后,我不敢保证完全理解了,至少下面的例子都可以一步一步的解释明白。
实验简单过程:
1) 将A、B主机连接到同一个hub上,防火墙什么的关闭,以免影响ping的结果;
2) 分别设置A、B主机的IP地址、网关地址等属性,然后使用ping命令;
关于ping的本质,这里不过多涉及了。不明白的可以搜索以下ICMP。
3)
下面先给一个ping过程的概述,然后按照这个模式来解释每个ping的具体过程,个人认为这样有利于理解ping的具体过程,同时又能把握总体方向。
当源主机发出ping命令时,网络层的ICMP协议封装好一个包,然后进行IP路由:
a)搜索路由表,寻找能与目的IP地址完全匹配的表目(网络号和主机号都要匹配,即整个IP都要完全相同)。如果找到,则把报文发送给该表目指定的下一站路由器或直接连接的网络接口(取决于标志字段的值);
b) 搜索路由表,寻找能与目的网络号匹配的表目(即看子网掩码与IP的逻辑与的结果是否相同)。如果找到,则把报文发送给该表目指定的下一站路由器或直接连接的网络接口(取决于标志字段的值)。目的网络上的所有主机都可以通过这个表目来处置。例如,一个以太网上的所有主机都是通过这种表目进行搜径的。
c) 搜索路由表,寻找标为“默认(default)”的表目,如果找到,则把报文发送给该表目指定的下一站路由器。
如果上面这些步骤都没有成功,那么该数据报就不能被传送。如果不能传送的数据报来自本机,那么一般会向生成数据报的应用程序返回一个“主机不可达”的错误。IP选路按照上面三个步骤顺序执行,只要有其中一个符合,就完成了选路工作,把数据报交给下一层――数据链路层。
在数据链路层时,对IP路由挑选出来的IP地址(注意不一定是最终的目标IP地址)进行如下步骤:
a) 如果在ARP缓存中存在该IP地址的MAC地址(使用arp –a命令察看),则将该MAC地址封装到帧里面,发送出去;
b.1) 如果该IP地址不是本机IP地址,则进行广播,获取该IP地址的MAC地址,并记录在ARP缓存中,然后将刚获取的MAC地址封装到帧里面,发送出去;
b.2) 如果该IP地址是本机的IP地址,嗯,这里有点问题了。
如果还是按照b.1)的方法,就会找到本机的MAC地址,然后发送出去。结果是本机接收到了这个ICMP,然后又按照上面的步骤一步一步下来,想想看,这是不是一个无法终结的死循环?(当然在以太网中超时就会放弃的)
这里为了避免这个情况,用了一个另外一个协议:代理ARP(arp proxy)。当选路出来的IP地址是本机IP地址时,并不是广播自己的IP地址,而是广播最终目标的IP地址。
这个时候(通常该最终目标地址都跟本机隔着一个路由器的),在该网段上的所有主机都不会相应这个广播,由路由器的代理ARP协议响应这个广播,把自己的MAC地址发送给源主机,说“最终目标的MAC地址是我的MAC地址(路由器‘欺骗’了源主机)”,然后由路由器接管这个帧,按照之前叙述的步骤进行发送。理解代理ARP是这个实验最难的地方。当然如果路由器关闭了代理ARP端口的话,就不能进行这样的操作了。
事实上,为了减少广播量,现在很多路由器都禁用了代理ARP端口。比如我们楼的路由器就禁止了这个功能。完成了数据链路层的操作之后,就进入到物理层,发送数据到目标主机了。至此,ping过程的叙述已经完成,下面看看具体的例子。
例1:
IP地址
|
子网掩码
|
默认网关
|
a主机:192.168.0.1
|
255.255.255.0
|
不填
|
b主机:192.168.1.3
|
255.255.255.0
|
不填
|
当a ping b时,按照3)中所述的步骤:
a) 搜索路由表,寻找能与目的IP地址完全匹配的表目(网络号和主机号都要匹配,即整个IP都要完全相同),找不到,进入下一步;
b) 搜索路由表,寻找能与目的网络号匹配的表目(即看子网掩码与IP的逻辑与的结果是否相同)。a主机的网络号为:192.168.0,b主机的网络号为:192.168.1,网络号不匹配,进入下一步;
c) 搜索路由表,寻找标为“默认(default)”的表目,a的默认网关没有,故在网络层该数据报无法发出,出现“主机不可达”的错误。由于没有到达数据链路层,故在a、b主机使用arp –a命令,均看不到对方的物理网卡地址。
b ping a的步骤同理可得。
例2:
IP地址
|
子网掩码
|
默认网关
|
a主机:192.168.0.1
|
255.255.255.0
|
192.168.0.1
|
b主机:192.168.1.3
|
255.255.255.0
|
192.168.0.1
|
当a ping b时,按照3)中所述的步骤:
a) 搜索路由表,寻找能与目的IP地址完全匹配的表目,找不到,进入下一步;
b) 搜索路由表,寻找能与目的网络号匹配的表目。a主机的网络号为:192.168.0,b主机的网络号为:192.168.1,网络号不匹配,进入下一步;
c) 搜索路由表,寻找标为“默认(default)”的表目,a的默认网关是192.168.0.1,IP选路完成,进入数据链路层。
数据链路层的步骤如下:
a) 在ARP缓存中是否存在该IP地址(192.168.0.1)的MAC地址,不存在,进入下一步;
b.2) 由于该IP地址(192.168.0.1)与源主机的IP地址(a)相同,故使用b.2)这步。广播最终目标的IP地址(192.168.1.3)。由路由器(192.168.1.3)的代理ARP端口响应这个广播,把自己的MAC地址发送给源主机(a),然后由路由器(192.168.1.3)接管这个帧,将该帧发给最终目的地址(192.168.1.3)。
当b成功接收到这个帧时,要发送一个ICMP应答给a主机,其步骤如下:
a) 搜索路由表,寻找能与目的IP地址完全匹配的表目,找不到,进入下一步;
b) 搜索路由表,寻找能与目的网络号匹配的表目。网络号不匹配,进入下一步;
c) 搜索路由表,寻找标为“默认(default)”的表目,b的默认网关是192.168.0.1,IP选路完成,进入数据链路层。
数据链路层步骤如下:
a) 在ARP缓存中是否存在该地址(192.168.1.3)的MAC地址,存在!数据链路层完成,成功发送ICMP应答给a。
至此,a ping b的整个过程都完成了。当b ping a的时候,步骤稍微有点不一样。
当b ping a时:
a) 搜索路由表,寻找能与目的IP地址完全匹配的表目找不到,进入下一步;
b) 搜索路由表,寻找能与目的网络号匹配的表目,网络号不匹配,进入下一步;
c) 搜索路由表,寻找标为“默认(default)”的表目,b的默认网关是192.168.0.1,IP选路完成,进入数据链路层。
数据链路层的步骤如下:
a) 在ARP缓存中是否存在该IP地址(192.168.0.1)的MAC地址,不存在,进入下一步;
b.1) 注意,由于b的默认网关跟本机的IP地址不同,故使用b.1)。由b的ARP协议进行广播,获取192.168.0.1的物理地址,并记录在b的ARP缓存中,然后将刚获取的MAC地址封装到帧里面,发送出去;
至此,b成功发送了一帧给a,a收到后,要给b一个ICMP应答,其步骤如下:
a) 搜索路由表,寻找能与目的IP地址完全匹配的表目,找不到,进入下一步;
b) 搜索路由表,寻找能与目的网络号匹配的表目,网络号不匹配,进入下一步;
c) 搜索路由表,寻找标为“默认(default)”的表目,a的默认网关是192.168.0.1,IP选路完成,进入数据链路层。
数据链路层的步骤如下:
a) 在ARP缓存中是否存在该IP地址(192.168.0.1)的MAC地址,不存在,进入下一步;
b.2) 按照之前叙述的代理arp方式,就能成功发送ICMP应答给b了。
哦,终于完成了一个简单的ping命令,是不是有点长?没办法,按照协议步骤执行下来就是这么冗长,好在电脑并不觉得这些烦琐的步骤麻烦。
例3:
IP地址
|
子网掩码
|
默认网关
|
a主机:192.168.0.1
|
255.255.254.0
|
不填
|
b主机:192.168.1.3
|
255.255.254.0
|
不填
|
当a ping b时,
a) 搜索路由表,寻找能与目的IP地址完全匹配的表目,找不到,进入下一步;
b) 搜索路由表,寻找能与目的网络号匹配的表目。a主机的网络号为:192.168.0,b主机的网络号为:192.168.0,网络号匹配, IP选路完成,进入数据链路层。
数据链路层的步骤如下:
a) 在ARP缓存中是否存在该IP地址(192.168.0.1)的MAC地址,不存在,进入下一步;
b.1) 广播IP地址(192.168.1.3),获取它的物理地址,封装成一个帧,进入物理层。
当b成功接收到这个帧时,要发送一个ICMP应答给a主机,其步骤如下:
a) 搜索路由表,寻找能与目的IP地址完全匹配的表目,找不到,进入下一步;
b) 搜索路由表,寻找能与目的网络号匹配的表目。网络号匹配,IP选路完成,进入数据链路层。
数据链路层的步骤如下:
a) 在ARP缓存中是否存在该IP地址(192.168.1.3)的MAC地址,存在!数据链路层完成,成功发送ICMP应答给a。
b ping a同理可得。
例4:
IP地址
|
子网掩码
|
默认网关
|
a主机:192.168.0.1
|
255.255.255.0
|
192.168.0.1
|
b主机:192.168.1.3
|
255.255.254.0
|
不填
|
当a ping b时,按照例2中a ping b的例子可得。当b接收到一帧数据之后,要给a一个ICMP应答,其步骤与例3中b ping a的步骤类似。
在例4中,如果加以改变,将a的默认网关也设为不填,将会出现一下情况:
当a ping b时:
a) 搜索路由表,寻找能与目的IP地址完全匹配的表目,找不到,进入下一步;
b) 搜索路由表,寻找能与目的网络号匹配的表目(即看子网掩码与IP的逻辑与的结果是否相同)。a主机的网络号为:192.168.0,b主机的网络号为:192.168.1,网络号不匹配,进入下一步;
c) 搜索路由表,寻找标为“默认(default)”的表目,a的默认网关没有,故在网络层该数据报无法发出,出现“主机不可达”的错误。由于没有到达数据链路层,故在a、b主机使用arp –a命令,均看不到对方的物理网卡地址。
当b ping a时:
a) 搜索路由表,寻找能与目的IP地址完全匹配的表目(网络号和主机号都要匹配,即整个IP都要完全相同),找不到,进入下一步;
b) 搜索路由表,寻找能与目的网络号匹配的表目(即看子网掩码与IP的逻辑与的结果是否相同)。a主机的网络号为:192.168.0,b主机的网络号为:192.168.0,网络号匹配,IP选路完成,进入数据链路层。
数据链路层的步骤如下:
a) 在ARP缓存中是否存在该IP地址(192.168.1.3)的MAC地址,不存在;
b.1) ARP广播目标IP地址,获取物理地址之后,封装一帧,发送到物理层。
至此,b将ICMP数据报成功发送给了a。a接收到之后,需要给b一个ICMP应答。发送ICMP应答的过程与a ping b的过程类似。所以,a不能成功发送一个应答给b。在a主机中出现“主机不可达”,而在b主机出现的信息是“超时”(注意IP是无连接服务,它只管是否发出)。使用arp –a命令,可以双方的物理地址。这证实了上面步骤的正确性,同时也说明了另外一个问题:即使拿到对方的物理网卡地址,如果网络层的IP路由失败,仍然无法进行数据链路层以上的层的通信,进一步加深了我对网络分层结构的理解。
例5:
IP地址
|
子网掩码
|
默认网关
|
a主机:192.168.0.1
|
255.255.254.0
|
不填
|
b主机:192.168.1.3
|
255.255.255.0
|
192.168.0.1(或1.3)
|
a ping b的原理同例3中的a ping b(b的应答不同),b ping a的原理同例2。在此不多叙述了,结论是能够成功ping通。
严格(至少我这么认为)的按照TCP/IP协议的ping过程已经给出来了,如果还需要了解更多的细节,可以查看
W.Richard Stevens
的
TCP/IP Illustracted Volume 1:The Protocols
(
TCP/IP详解 卷1:协议
)。文章中关于IP选路的步骤完全摘录自该书。
两台主机的例子基本都涉及到了,三台甚至多台的原理与之类似。当初为了解释这几个例子的时候花了挺多的时间,现在想起来还不错,至少理解了这小部分的原理。关于代理arp这部分很多人可能起先感到惊讶,这都能ping通?开始我问一个前辈的时候也有类似的反应,不过查阅了资料并亲自实践之后不再迷茫了。
由于小弟只涉及到很浅的方面,所以如果文章中有错误,欢迎大家指正,也算是共同学习吧。