DHCP 主要有四个过程: discover、offer、request、ack。
 

step 1:
客户端(PC机或移动终端)以广播包的形式,找寻可以提供分配ip的服务器或路由器,这即为discover阶段。

 
step 2:
所有收到这个discover广播包,并且可以有分配IP功能的服务器或路由器,会回应这个广播包;发包的方式可能是广播报文,也可能是 单播报文 (这因路由器的不同而可能不同)。这即为offer阶段

 

step3:
客户端收到这个包后(虽然这时候网络中有很多offer报文,但此时只会接受第一个到达的offer报文),从这个offer报文中提取所要的ip,dns,net gate,并根据IP计算submask, 然后以广播包的形式,告知所有的可分配IP的服务器或路由器我已经得到一个IP,并且此报文中包含了为客户端分配IP的服务器或路由器的信息。这即为request阶段。
 

step4:
所有的路由器或服务器收到这个request广播包之后,从中提取服务器的信息,如果是指向自己的,则会回ACK(同样,因路由器的不同回ACK的方式可能是广播报文,也可能是单播报文 ),其他的服务器或路由器则不会回ACK。这即为ACK阶段。
=====================================================================


问题一:
我在调试板子的时候,出现过这种情况: 我有两块板子同时向局域网发送DHCP请求,结果获取到的IP竟然是相同的,这是为何?

 

原因 :
最终查到的原因是,我在组discover包的时候,将dhcp discover包中的Transaction ID写成固定值了,即两块板子发送出去的 discover报文中的Transaction ID是相同的; 并且当时的那个路由器是以广播包的方式发送offer报文和回应ack报文的。那么当我的两块板都收到这个广播包的时候,并且发现offer和ack报文中的Transaction ID和自己发出去的是一样的,那么就理所当然的认为这个IP是分配给自己的,所以导致两者的IP是一样的。

 
解决办法:
将这个Transaction ID改为随机数即可。

 
小结:
在DHCP的四个步骤中,Transaction ID 是一样的,也就是说要根据Transaction ID来判断报文是否匹配,即判断这个报文是否是自己需要的DHCP报文。此处有个例外,如果路由器是以单播报的形式发送offer、ACK报文,那么即使Transaction ID是写成固定了,也不会出现分配相同IP的问题,因为可以根据offer、ACK报文中的目的MAC地址区分开来。
--------------------------------------------------------------------------------


问题二:
解决了问题一之后,又发现了一个新的问题:板子获得了IP之后,比如说获得的ip是"192.168.2.3" ,这时候我用PC也连同一个路由器, 并且把pc的ip手动设置为"192.168.2.3" ,马上可以看到电脑显示IP冲突。但是在我的板子上如何检测IP是否冲突?

 

解决办法:
在获取了IP之后,在板子上通过发送一个ip detect 的ARP request报文即可达到检测IP是否冲突的目的。在这个ARP request报文中,sender ip 和 destination ip 都指向自己获得的ip(这里即为192.168.2.3),发出去之后。拥有"192.168.2.3"这个IP的pc机收到这个ARP request之后,或回应一个ARP reply的报文,并且此报文中的sender ip 和 destination ip相同(这里都为192.168.2.3)。 那么只需在我的程序中判断收到的ARP reply报文中的sender ip 和 destination ip是否相同就可以判断板子的IP是否和PC机或移动终端发生了冲突。
----------------------------------------------------------------------------------

 
问题三:
检测IP冲突之后,如何重新获取ip?开始的时候,我仅仅在程序中重新发一次dhcp discover 报文,并且重新进行了一次DHCP的四个步骤,结果发现获取的ip和上次的是相同,依然会有冲突, 为什么会相同? 如何让重新获取的IP不同?

 
原因:
因为路由器中有个ARP cache, 当我们的板子先获得一个IP之后,路由器的ARP cache中就会记录板子的IP和MAC(两者一一对应)。然后,通过手动强制设置的IP地址的pc机(IP和板子的一样)的mac并不会被ARP cache所记录,因为arp cache中一个IP只能对应一个MAC地址。所以后来板子重新DHCP获得的IP的时候,路由器发现ARP cache中有我的板子的MAC对应的IP,那么路由器就会将这个IP分配给我的板子。所以出现了即使重新DHCP,获取的IP仍和上一次相同的情况。

 
解决办法:
那么我们就得想办法,让路由器知道我们不要现在的这个IP了,告诉路由器重新分配一个不同的ip给我们。怎么让路由器按这个要求工作呢? 通过抓包工具抓取的PC机上的报文,我发现DHCP除了上面的四种报文,还有另外一种: DHCP Decline 报文。 这个报文的作用是告诉路由器"我目前的这个IP已经不想再用了,请将我的这个MAC和这个IP的对应关系从你的ARP cache中删除"。这个报文是以广播包的形式发送的。发送了DHCP Decline报文之后,再发DHCP discover 报文,并进行DHCP的四个步骤即可获取到新的IP。
===================================================================


下面的链接是我用Ethereal工具抓到的我的板子、PC机发送的DHCP的5种数据包。通过数据包的分析是学习TCP/IP的最直观的方法。
http://download.csdn.net/source/1986344
在Ethereal内的filter框输入bootp即可过滤出DHCP的数据包

 posted on 2011-10-26 11:43  Braincol  阅读(6505)  评论(1编辑  收藏  举报