三十天学不会TCP,UDP/IP网络编程 - UDP的实践--DHCP

在经历了一顿忙碌加出去玩了玩之后,我又开始重新更新了~这是最新的一篇~完整版可以去gitbook(https://www.gitbook.com/@rogerzhu/)看到,在gitbook的后台流量上看到了有很多盆友都看了我目前写的这么多文字,说实话,真心是有点感动,也有很多的成就感。正是这种感动支撑着我在玩回来和“快过年了,有事节后再说”的双重懒惰压力下,我觉得我还是在有空的时候更新下文字。

如果对和程序员有关的计算机网络知识,和对计算机网络方面的编程有兴趣,虽然说现在这种“看不见”的东西真正能在实用中遇到的机会不多,但是我始终觉得无论计算机的语言,热点方向怎么变化,作为一个程序员,很多基本的知识都应该有所了解。而当时在网上搜索资料的时候,这方面的资料真的是少的可怜,所以,我有幸前两年接触了这方面的知识,我觉得我应该把我知道的记录下来,虽然写的不一定很好,但是希望能给需要帮助的人多个参考。我的计划是用半年时间来写完这一系列文章,这个标题也是我对太多速成文章的一种态度,好了,废话不再多扯了,下面是其中的一节内容,更多内容可以去gitbook上找到。

每个上网的人都知道,每个终端都有一个IP地址,而前面说过IANA只负责分配大节点的IP地址,不可能小到每一个终端系统都由这么一个机构来分配具体的IP地址。所以当IANA分配完大的IP地址段之后,每个IP地址段的地址由各个子网自己负责分配,而如何保证分配的地址不重复而且能够被回收关系到IP地址的有效使用的问题,因为毕竟一个子网的IP地址是有限的。而这件事情就是由DHCP来负责的,而DHCP协议就是一个工作在UDP上面的广泛运用的协议。

DHCP概述

DHCP学名“Dynamic Host Configuration Protocol”,翻译过来就是动态主机配置协议,它还有个初代产品,叫做bootp, 这也是为什么在wireshark里面是搜不到DHCP而必须使用bootp来过滤得到DHCP数据包的原因。DHCP可以在局域网中很好的起到分配IP地址并且提供管理功能,这样使得每个机器在有DHCP服务器的情况下都能方便而又快捷的获得IP地址。DHCP在server端和client端分别使用不同的端口号进行通信,在server端是用的67而在client端是68。

DHCP的报文中大部分信息都是和IP地址相关的,是时候再一次献上我的手绘版:

三十天学不会TCP,UDP/IP网络编程 - UDP的实践--DHCP

三十天学不会TCP,UDP/IP网络编程 - UDP的实践--DHCP

其中前4个字节主要是一些信息相关的,比如:

字节1:消息操作码,顾名思义,用来标识这是咋样的一个DHCP数据包

字节2和字节3:硬件类型和硬件地址长度

字节4:跳数,这个可以忽略它

字节5-8:消息的标识,用来标识一组消息。

字节9-10: 从获取到IP地址或者续租过程到现在所消耗的时间,至于什么叫租期和续约会在后面详细说明

字节11-12:标记

字节13-16:客户IP地址

字节17-20:申请IP地址回复中客户机的IP地址,这句话有点拗口,所以叫"Your IP Address“,你的IP地址,虽然说俗了点,但是不会乱

字节21-24:在DHCP中使用的下一台服务器的地址,这个要联系具体的过程看,一下子就能明白是什么意思

字节25-32:用于导入接替代理的IP地址,在这一节文章中可以忽略

字节33-48:客户机硬件地址,也就是“你的硬件地址”

字节49-112:任意服务器主机名称,以null作为终止符

字节113-240:在DHCP协议中使用的引导文件名称

剩下的变长部分是一些DHCP协议中可能使用的选项。

这一系列罗列枯燥无味,不需要花任何功夫去记忆或者试图强行理解他们,除非你需要他们来装b,因为结合下一节,你会发现其实这些可以很自然的被记忆。

“DORA”

当你看完这节介绍之后,即使你没有记住DHCP的大部分细节,你只要记住这个“DORA”过程就已经了解所有DHCP的过程,在具体介绍"DORA"之前,为了风格的一致性,先来概要的介绍下DHCP协议。

“DORA”这个缩写是Discover,Offer,Request和Acknowledge的统称,反映的是DHCP协议交互的四个步骤,在经过这四个步骤以后,一个客户端就获得了地址,通信的草图请看我的灵魂画稿:

三十天学不会TCP,UDP/IP网络编程 - UDP的实践--DHCP

三十天学不会TCP,UDP/IP网络编程 - UDP的实践--DHCP

下面来具体介绍下这个四个步骤,大致过程是这样的:

Dicovery -- 探索阶段,可以理解为客户机取服务器探索有没有可以用IP地址。在这一个阶段,由于客户机并不知道服务器在哪里,所以他会在网络上发送一个广播,而在DHCP报文中的客户端MAC地址中填入自己的MAC地址。而且可以在选项中加入自己的最后一个申请的IP地址,当然前提是你有IP地址,这样如果该地址仍然处于IP地址池的可用状态,如果是授权的服务器,服务器会直接接受,而如果是非授权的服务器,服务器会直接拒绝这个请求,然后让客户机重新申请新的IP。

Offer -- 服务器在收到探索阶段的数据包之后,搜索自己管理的IP地址池并且在验证在当前分配策略下仍然有可用的IP地址之后,它会选择一个IP地址并且将其填入Your IP address字段。在大多数情况下,服务器会把一些其他重要信息填入选项字段,比如子网掩码,DHCP服务器地址,这个地址在多少时间内可以不需要再一次探索是否可用,也就是租期等等。所以你可以在客户机上看到,当用户拿到IP地址后,也会拿到子网掩码等等这些信息。

Requst-- 客户端在收到服务器提供的IP地址之后,理论上应该就结束,最多再发一个确认消息就可以了,那么为什么会有这个request消息呢,这个消息的产生是因为一般一个局域网中不会只有一个DHCP服务器,客户再次以广播消息的方式发送DHCP数据包,这一次客户机会把给自己提供IP地址的服务器地址放在option里面并且加上自己的IP地址,这样做的目的是让其他DHCP服务器收回自己可能已经提供出去的客户机的IP地址,重新放入地址池,因为此时客户机已经拥有了自己的IP地址。

Acknowledge--服务器的最后确认,这个时候整个过程就全部结束了。

在继续看一看这里面更有意思的一些的细节之前,我觉得应该使用一个现实的抓包例子免得文章陷入于说明的无聊之中,在windows上如果你想抓一个完整的DHCP整个过程的数据包,出来要打开wireshark并且输入bootp(不是dhcp)作为过滤器之外,你只需要采用ipconfig -release 命令再加上ipconfig -renew命令。如果你只用ipconfig -renew命令,绝大数情况下你只能看到request和ack消息,后面会说明一下这是为什么。

三十天学不会TCP,UDP/IP网络编程 - UDP的实践--DHCP

三十天学不会TCP,UDP/IP网络编程 - UDP的实践--DHCP

从这个抓包截图至少可以看出这么几个信息,在discover和request阶段,客户机这边全是广播的消息,而客户机被分配的IP地址是192.168.11.44,接着就是一组请求使用一个transaction ID,也就是DHCP数据包中xid字段。至此,客户机就拥有了自己的IP地址。而一般在得到这个IP地址之后,客户机会向网络广播一个ARP消息其中的IP地址就写自己刚刚获得IP地址,如果你还记得前面的内容,那么就会记得这样做的目的是看看网络上会不会产生网络冲突,再一次确认在当前局域网中没有相同的IP地址被使用,从而可以放心的使用这个IP地址。

在上面的过程中,Discover和Request的操作码都是1,而剩下的两个都是2,那么服务器到底怎样分辨是discover还是request呢?答案是DHCP报文里面的option字段,具体的说是option 53,在这里会标识出到底是Dicover还是Request,是Offer还是Acknowledge。

另外一个有意思的事情是DHCP报文包里会有一个magic cookie,是一个固定值,为0x63825363,十进制就是99 130 83 99,是不是特别像一个IP地址?为什么会有东西,原因是因为前面说的Bootp和DHCP在报文格式上完全相同,如果没有这么一个东西,完全无法分辨到底是什么报文,至于为什么是这个值,我也不知道,只能说规定如此。

租约

试想一下这样的问题,当某一个客户机获取了IP地址之后,然后这个机器就从这个网络上移除了,DHCP服务器如何知道这个IP地址现在不需要被用从而重新放入可分配的IP地址池中呢?对于现在最常见的就是手机,一下子连在这个WIFI上,一下子连在那WIFI上,甚至很多时候某一个WIFI只会连一次以后再也不会去那个地方也就再也不会连上某个WIFI。当我写下这个例子的时候,深深感到技术时代发展之快,要知道前几年,这个例子的主题还是笔记本电脑。某一个客户机在离开一个局域网时不会自动发一个release消息给DHCP服务器的,因为这很难做到,离开意味着你已经不和这个网络相连接了,如何能够发消息给DHCP服务器?

为了解决这个问题,在DHCP的机制里,租期和租约是一个很重要的概念,客户机获取到的IP地址并不真正属于他,而是向DHCP服务器租的,这个时间一般是48个小时。在48个小时之后,被分配出去的IP地址又会重新返回IP池作为可分配的IP,而如果在这48个小时之内,客户机再一次请求续租这个IP地址,那么服务器端就会重新设置计数器,直到下一个48小时到期。

具体怎么做到这一点呢?如果你还记得前面Request或者Discover阶段中,一个用户可以把自己的IP地址写在Option字段,如果服务器是授权可以分配该IP地址的,那么就会直接得到IP地址,这就是“续租”。所以如果在前面不用ipconfig -release 然后使用ipconfig -renew的话,单独的ipconfig -renew只会产生两个消息,因为这只是一个续租的过程。

其实对于DHCP租期这个事情可以有一个很直观的认识,前提是你每天来公司会有看看自己IP地址的需求,你会发现,有时候你的IP地址好几天都不变,而当周末回来周一重新连上网络的时候,往往IP地址变了,这就是前面说的租期和租约的原理。

上一篇:Building a Space Station POJ - 2031


下一篇:[Unity菜鸟] 笔记2 —— 问题篇