网络工程师(12):让IP更容易得到

我们从开始到现在,用了十一篇小文章讨论和解决了网络中的基本通信问题。以后的主要任务,是对网络进行优化:比如让网络在速度、性能、健壮、安全等多方面进行提升,比如可以更容易上网,比如让网管人员工作更轻松,等等。当然,还可以根据需要,给网络增加新的功能。

第一个要优化的,就是IP地址!

IP地址?这还能怎么优化?

IP地址标识了你在网络中是谁,别人找你或者你找别人都会用到它。可是,在电脑上配置IP地址可不是件容易的事,需要你了解IP地址、掩码、网关等知识。可是咱不能因为不懂这些就不能上网呀,所以得有个解决办法。

DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)就是一个能让电脑获得IP地址的协议。

DHCP是一个应用层协议,分为服务端和客户端,基于UDP传输,端口号服务端使用67,客户端使用68。需要IP地址的电脑都可以叫客户端。当电脑开机后,可以自动从服务端获取所需的IP地址、掩码、网关等信息,完全不需要我们参与。

我们来讨论下DHCP都干了啥。

客户端电脑开机后,会自动产生一个叫DHCP Discover的报文,写入自己的MAC地址,然后交给传输层UDP封装,源端口号填写68,目的端口号填写67,向下交给网络层IP。IP封装时,源IP地址填写0.0.0.0(客户电脑还没有IP地址),目的IP地址填写255.255.255.255(客户端没有IP地址,并不知道自己在哪个网段,所以无法使用网段广播地址。当然更不知道DHCP服务器在哪,所以只能封装一个全网广播地址),协议号填写17(表示是UDP给下来的。TCP的还记得不?),向下交给链路层以太网,以太网封装时填写源MAC地址为客户端电脑的MAC,目的MAC填写FFFF-FFFF-FFFF广播地址,Type填写0x0800。封装完成后发送出去。

服务端收到后,记录Discover报文中的MAC地址,产生一个DHCP Offer报文,把准备分配给客户端的IP地址、掩码、网关、租期、客户端MAC等信息写在报文中,交给UDP。UDP封装源端口号67,目的端口号68,交给IP。IP封装源地址为DHCP服务器地址,目的地址为255.255.255.255,协议号17,交给以太网。以太网封装源MAC为服务器MAC地址,目的地址为FFFF-FFFF-FFFF广播地址,Type为0x0800。封装完成后发送出去。

客户端收到Offer报文后,检查里面的MAC如果是自己的,会封装一个Request报文发出去。为什么要发这个Request呢?Offer报文里IP信息都有了,客户端干嘛不直接用,还要Request请求一下呢?

这是因为,网络中可能存在多台DHCP服务器,每台服务器收到Discover后,都会预留一个预分配地址并写进Offer发出去,客户端可能会收到多份Offer。所以,客户端发出Request的目的就是做一个选择,只能要一个DHCP服务器分配的地址,并把选择的DHCP服务器的IP地址写在Request中,其他服务器收到Request后,发现没有选择自己,就会把刚才准备分配的IP地址释放掉。

客户端一般选择收到的第一个Offer。

Request的IP封装中,源地址为什么不使用服务器在Offer中分配的地址,还是使用0.0.0.0呢?

主要原因是现在还不知道有没有其他人在使用这个地址。如果网络中的地址全是由同一台DHCP服务器分配的,不会出现地址冲突。但更多情况下,有很多设备的IP地址是手工填写的,而这些手工填写的IP地址,DHCP服务器并不知情。

服务器收到Request报文后,看看里面的MAC地址之前有没有记录过,如果有,则把客户端MAC写进DHCP ACK报文,封装后发出去。ACK报文内容和封装与Offer报文基本相同。如果没有,则把这个Request报文中携带的客户端MAC封装进一个NAK消息中发出,通知这个客户端无法给它分配地址(意思是服务器没有收到这个客户端的Discover,直接收到了它的Request。如果收到Discover肯定有记录)。客户端收到NAK后会重新发出Discover申请地址。

客户端收到ACK报文后,封装一个免费ARP报文,Sender IP和Target IP都填写为服务器分配的IP地址(在服务器发的Offer和ACK报文中都有)发出去,检查此地址是否可用。如果收到ARP Reply回复,则表示此地址已被使用,客户端则封装一个DHCP Decline报文发给服务器,告诉服务器禁用这个地址,然后发出Discover重新开始地址申请。若客户端没有收到ARP Reply,表示此地址可用,开始使用这个地址并开始计算租期。

我们可以发现,客户端在申请地址过程中,需要与服务器进行多次通信,双方每次通信基本靠“吼”(广播),如果客户端数量较多,就要考虑大量报文在传输中别出岔子。把客户端MAC地址写进每个报文中是最好的办法。不然服务器说这个Discover谁发的呀,客户端说这个Offer是给谁分配的地址呀,如果大家都用第一个Offer,地址不就冲突了嘛。

客户端在使用地址期间,随时可以通过DHCP Release报文释放此地址。服务器收到Release报文后,收回该地址重新参与分配。

客户端使用地址的时间到达租期的50%时,会封装DHCP Request报文发出(对,还是Request,只是这个Request封装的源IP是客户端正在使用的IP地址,目的IP是DHCP服务器的IP地址,两人单播联系,小声耳语,别人听不到),服务器收到后,回复DHCP ACK报文。如果客户端收到这个ACK报文,则重新计算租期,否则继续使用这个地址。

当客户端使用地址的时间到达租期的87.5%时,再次封装DHCP Request报文发出(这个Request跟50%那次有点不同,目的地址不是DHCP服务器的IP地址而是255.255.255.255广播地址。因为上次单播时服务器没有理我,没办法只好再次使出“狮吼功”),服务器收到后,回复DHCP ACK报文。如果客户端收到ACK,重新计算租期,否则依然继续使用这个地址。

当客户端使用地址的时间到达租期,则封装DHCP Release释放此地址,重新开始新的地址申请过程(“吼”了也没人理我,算了这个地址我不要了,重新申请去)。

我们举个栗子:假如地址租期为24小时(一般默认是这个时间)。客户端使用地址12小时,小声单播发出DHCP Request报文,如果收到服务器的ACK报文,则重新计时。否则继续使用但不重新计时。使用到21小时,大声吼出Request报文,如果收到ACK,租期重新计算,否则继续使用但不重新计时。使用到24小时,客户端发出Release释放这个地址不要了,重新发Discover申请地址。

我们发现,虽然UDP协议不可靠,但DHCP已有应对办法。关键是,因为客户端没有IP地址,根本无法使用TCP去建立连接。所以,UDP协议在很多场合下非常有用,并没有因为它不可靠而显得不堪。通常,应用程序使用UDP作传输协议时,都已经解决了它不可靠的问题。


小Q:地址申请过程中的Discover、Offer、Request和ACK都被IP和以太网封装成了广播,那么,如果服务器和客户端不在同一个网段怎么办?

欢迎留言讨论。

你可能感兴趣的:(网络工程师(12):让IP更容易得到)