DHCP服务器的设计

介绍

DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)通常被应用在大型的局域网络环境中,主要作用是集中的管理、分配IP地址,使网络环境中的主机动态的获得IP地址、Gateway地址、DNS服务器地址等信息,并能够提升地址的使用率。

DHCP协议采用客户端/服务器模式。客户机登录服务器时可以自动获得DHCP服务器分配的IP地址和子网掩码,这也是现在接入网技术中供应商给用户(账号)提供IP地址的手段。

原理

端口

首先DHCP是基于UDP的两个端口实现的,DHCP提供服务时,客户端以68号端口进行数据传输,服务器端以67号端口进行数据传输。

DHCP报文类型

DHCP一共有8中报文,分别为DHCP Discover、DHCP Offer、DHCP Request、DHCP ACK、DHCP NAK、DHCP Release、DHCP Decline、DHCP Inform。

DHCP Discover: DHCP客户端在请求IP地址时并不知道DHCP服务器的位置,因此DHCP客户端会在本地网络内以广播方式发送Discover请求报文,以发现网络中的DHCP服务器。所有收到Discover报文的DHCP服务器都会发送应答报文,DHCP客户端据此可以知道网络中存在的DHCP服务器的位置。

DHCP Offer:DHCP服务器收到Discover报文后,就会在所配置的地址池中查找一个合适的IP地址,加上相应的租约期限和其他配置信息(如网关、DNS服务器等),构造一个Offer报文,发送给DHCP客户端,告知用户本服务器可以为其提供IP地址。但这个报文只是告诉DHCP客户端可以提供IP地址,最终还需要客户端通过ARP来检测该IP地址是否重复。

DHCP Request:DHCP客户端可能会收到很多Offer请求报文,所以必须在这些应答中选择一个。通常是选择第一个Offer应答报文的服务器作为自己的目标服务器,并向该服务器发送一个广播的Request请求报文,通告选择的服务器,希望获得所分配的IP地址。另外,DHCP客户端在成功获取IP地址后,在地址使用租期达到50%时,会向DHCP服务器发送单播Request请求报文请求续延租约,如果没有收到ACK报文,在租期达到87.5%时,会再次发送广播的Request请求报文以请求续延租约。

DHCP ACK:DHCP服务器收到Request请求报文后,根据Request报文中携带的用户MAC来查找有没有相应的租约记录,如果有则发送ACK应答报文,通知用户可以使用分配的IP地址。

DHCP NAK:如果DHCP服务器收到Request请求报文后,没有发现有相应的租约记录或者由于某些原因无法正常分配IP地址,则向DHCP客户端发送NAK应答报文,通知用户无法分配合适的IP地址。

DHCP Release:当DHCP客户端不再需要使用分配IP地址时,就会主动向DHCP服务器发送RELEASE请求报文,告知服务器用户不再需要分配IP地址,请求DHCP服务器释放对应的IP地址。

DHCP Decline:DHCP客户端收到DHCP服务器ACK应答报文后,通过地址冲突检测发现服务器分配的地址冲突或者由于其他原因导致不能使用,则会向DHCP服务器发送Decline请求报文,通知服务器所分配的IP地址不可用,以期获得新的IP地址。

DHCP Inform:DHCP客户端如果需要从DHCP服务器端获取更为详细的配置信息,则向DHCP服务器发送Inform请求报文;DHCP服务器在收到该报文后,将根据租约进行查找到相应的配置信息后,向DHCP客户端发送ACK应答报文。目前基本上不用了。

DHCP报文格式

我们通过抓包看一下DHCP的报文:

图片.png

1.Message type:Boot Request(1)当为1时表示是client的请求,为2时是server的应答

2.Hardware type是网络硬件地址类型

3.Hardware address length表示网络硬件地址长度(6Bytes表示是以太网类型的MAC地址)

4.HOPS表示跳数,是当前的DHCP报文经过的DHCP RELAY的数目,每经过一个DHCP中继,此字段就会加1;当这个字段大于4时,DHCP报文直接丢弃。

5.Transaction id:事务ID,是DHCP请求报文时选择的随机数

6.Elapsed boot time描述,表示client开始DHCP请求后的时间流逝秒数

7.flags标志

8.Client self-assigned IP address:客户机IP地址

9.Client IP address:分配给client的IP地址

10.Next Server IP address:服务器IP地址

11.Relay AgentDHCP:中继代理IP地址

12.Client Hardware address客户机硬件地址MAC

13.Client Hardware address padding:客户机硬件MAC填充地址

14.Host Name:服务器的主机名

15.Boot File name:是client的启动配置文件名

16.Magic cookie是服务器可以根据这个cookie直到该用户是否需要重新登录。

之后的字段会根据报文类型而有不同的改变:

17.DHCP Message Type:此字段表示DHCP报文类型

18.DHCP Server Identifier是DHCP Server的报文类型

19.Client identifier:客户端报文类型

图片.png

交互过程

图片.png

通过观察抓包顺序可以知道是,客户端首先从68端口发出广播(UDP报文)即discover报文寻找DHCP服务器,请求租用IP地址。该广播包中的源IP地址为0.0.0.0,目标IP地址由于是广播所以为255.255.255.255,报文中还包含客户机的MAC地址和计算机名。DHCP服务器会将67端口开启,收到客户端的discover报文后会回应一个offer报文,此报文的源IP地址为服务器的IP,目标IP地址为255.255.255.255,数据报中还包含着提供的IP地址、子网掩码、网关、DNS及租期等信息。

然后客户端就会广播一个request报文,表示自己已经接受了一个DHCP服务器提供的IP地址,广播包中包含所接受的IP地址和服务器的IP地址。服务器在接收到request广播后,会广播返回给客户机一个ACK消息包,表示已经接受了客户机的选择,并将这一IP地址的合法租用以及其他的配置信息都放入该广播包发给客户。此客户此时就已经获得一个可用的IP地址。整体流程如下图:

图片.png

代码设计

首先工程的结构如下:

---dhcpserver||--DHCPOptionEnum.h|--maker.h--parser.h|--stdafx.h|--Mystruct.h||--DHCPserver.cpp

代码是基于DHCP的原理、报文以及DavidAnson的DHCPLite0的代码逻辑框架。下面将逐一分析一下代码:

main函数

逻辑是首先获取运行环境下的网络设备所有网卡信息,然后以"链表"的形式存储在PIP_ADAPTER_INFO结构体所声明的AdapterWalker对象中,然后将需要选择的网卡信息作为输入与bindInterfaceAddress进行绑定。以上都是初始化信息,主要是为了让用户选择需要进行绑定的网络设备。

然后m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (char*)&optval, sizeof(bool))将套接字设置为UDP格式,同时通过setsockopt对套接字的功能进行设置,是套接字是符合我们想做为DHCP的广播环境的。之后创建一个线程thread mThread(ClientListen, bindInterfaceAddress)用来模拟客户端进行广播消息的交互。

接下来就是服务端与客户端的报文交互了,我们需要处理好的就是报文格式以及相应的判断就行了。主要就是在客户端发来报文后,服务端进行解析(parse),解析完成后再回应一个报文,需要先制作(make)一个报文。通过这样完成报文的交互。

ClientListen

这个函数是在新线程下用来模拟客户端的,所以逻辑是与主函数相同的。由于是线程,可以模拟多个客户。

GetIpFromTable

在这里利用了一个unordered_map的存储方式,因为利用map存储数据不论是插入还是查询的速度都是非常快的。在这个结构里我们将已经申请了IP地址的客户放入这个结构中,如果有就返回信息;如果没有这个客户,则加入这个用户的IP地址及信息。

MyStruct.h

在这里定义了DHCP报文格式的结构体

struct DHCP_PACKET {byte OP;byte HTYPE;byte HLEN;byte HOPS;UINT32 TRANSACTION_ID;UINT16 SECONDS;UINT16 FLAGS;byte ciaddr[4];byte yiaddr[4];byte siaddr[4];byte giaddr[4];byte chaddr[16];byte sname[64];byte file[128];UINT32 magicCode;byte Options[308];
};

同时定义了Packet_Information的结构体:

struct Packet_Information {char HostName[256];USHORT BootFileSize;char MeritDumpFile[256];byte DHCPMessageType;int IPLeaseTime;          // clientbyte ServerIdentifier[4]; // clientbyte ClientIdentifier[4];byte ParameterRequestList[256];byte VendorClassIdentifier[256];byte RequestedIPAddress[4];byte Unsupport[256];bool OptionToReplay[256];
};

parser.h与maker.h

这里直接调用了解析与封包的相关函数,主要是对IP地址、端口以及相应数据报格式字段信息的转换,判断与赋值。

DHCPOptionEnum.h

这个头文件定义了DHCP Option的所有情况,利用enum结构进行存储;在主函数中调用时就可以通过数字进行表示与区分。

结果

图片.png

图片.png

项目请见:Github

转载于:https://www.cnblogs.com/yunlambert/p/9297358.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/413755.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Dom对象、JavaScript对象、jQuery对象区别

一、Dom对象、JavaScript对象、jQuery对象 1.1 Dom对象 文档对象模型简称DOM,是W3C组织推荐的处理可扩展置标语言的标准编程接口。 DOM实际上是以面向对象方式描述的文档模型。DOM定义了表示和修改文档所需的对象、 这些对象的行为和属性以及这些对象之间的关系。…

[vue-cli] vue-cli工程中常用的npm命令有哪些

[vue-cli] vue-cli工程中常用的npm命令有哪些 npm install:下载 node_modules 资源包的命令 思考问题: 为什么下载资源包要用npm install? 请你谈一下 npm run dev: 启动 vue-cli 开发环境的 npm命令(3.0以下&#x1…

Spring对AspectJ的支持

1.AspectJ介绍及Pointcut注解应用 (1)AspectJ AspectJ的风格类似纯java注解的普通java类Spring可以使用AspectJ来做切入点解析AOP的运行时仍旧是纯的Spring AOP,对AspectJ的编译器或者织入无依赖性(2)Spring中配置Aspe…

[vue-cli]在使用vue-cli开发vue项目时,自动刷新页面的原理你了解吗?

[vue-cli]在使用vue-cli开发vue项目时,自动刷新页面的原理你了解吗? 自动刷新页面并不是vue-cli的功能,而是webpack的hot-module-replacement-plugin插件在做这件事,这个插件是webpack自带的插件,用来做hmr的。如果需…

git 基本使用

一、本地创建git版本库 在本地随便找个空文件夹 或者 新建一个空文件夹 初始化一下 $ mkdir newgit //新建一个空目录 $ cd newgit //进入 $ git init //使用git init命令 初始化一个Git仓库二、添加文件到Git仓库&#xff0c;分两步 使用命令git add <f…

C++ ActiveX开发的问题讨论

最近在一个项目中需要开发一个ocx插件&#xff0c;在开发过程中发现了一些问题&#xff0c;所以在此记录一下。 我想讨论的主要是函数的参数问题&#xff0c;我分别使用c,JavaScript,C#对ocx插件做了测试&#xff0c;发现不同的参数类型在这几种语言中表现的差异很大。 &#x…

[vue-cli]vue-cli3插件有写过吗?怎么写一个代码生成插件?

[vue-cli]vue-cli3插件有写过吗&#xff1f;怎么写一个代码生成插件&#xff1f; MyPlugin.install function (Vue, options) { // 1. 添加全局方法或属性 Vue.myGlobalMethod function () { // 逻辑... }// 2. 添加全局资源 Vue.directive(my-directive, { bind (el, bindi…

javaScript数据类型(包括基本数据类型和非基本数据类型)

一、五种基本数据类型 1、number 数字类型 - 包括浮点数和整数&#xff0c;例如&#xff1a;1,100,3.14 2、string 字符串类型 - 包括任意数字字符组成的序列&#xff0c;例如&#xff1a;“1”&#xff0c; “one”&#xff0c; “one 2 one” 3、boolean 布尔类型 - 包括 t…

Codeforces Round #496 (Div. 3 ) E1. Median on Segments (Permutations Edition)(中位数计数)

E1. Median on Segments (Permutations Edition)time limit per test3 secondsmemory limit per test256 megabytesinputstandard inputoutputstandard outputYou are given a permutation p1,p2,…,pnp1,p2,…,pn. A permutation of length nn is a sequence such that each i…

数组转换为字符串方法

1. toString() 方法 和 toLocaleString() 方法 var arr [ "a", "b", "c"]; alert(arr.toString()); // a,b,c alert(arr.toLocaleString()); // a,b,c 返回数组的字符串表示&#xff0c;中间以逗号隔开 2. join() 方法 var a…

[vue-cli]vue-cli生成的项目可以使用es6、es7的语法吗?为什么?

[vue-cli]vue-cli生成的项目可以使用es6、es7的语法吗&#xff1f;为什么&#xff1f; vue-cli 配置了babel,可以将es6,es7....etc在webpack打包的时候转换成es5的代码&#xff0c;所以上线的时候没有问题。但是脚手架只是配置了一些默认常见的用法&#xff0c; 可以根据babel…

做小程序的流程总结(基本篇)

一、首先当我们借助小程序实现我们的网站搭建时&#xff0c;就需要使用小程序自带的一些功能&#xff1b;且需要根据该小程序获取到的一些参数存储到对应的数据库中。 openID&#xff1a;每个微信用户使用该小程序时都会产生一个openID&#xff0c;且该openID是唯一标识&#x…

js对象数组 按对象的某一属性进行去重

var array [{ id: 1, name: "张三"},{ id: 2, name: "李四"},{ id: 3, name: "张龙"},{ id: 4, name: "赵虎"},{ id: 5, name: "王朝"},{ id: 1, name: "刘金刚"},{ id: 6, name: "马汉"}, ]var obj …

[vue-cli]vue-cli怎么解决跨域的问题?

[vue-cli]vue-cli怎么解决跨域的问题&#xff1f; 在根目录下新建&#xff1a;vue.config.js注意名不能错误&#xff0c;然后里面配置 module.exports { devServer: { proxy: { //配置跨域 /api: { target: 跨域url, ws: true, changOrigin: true // pathRewrite: { // ^/api…

java - springmvc整合cxf发布webservice

1.jar包已上传百度云盘&#xff0c;在jar包目录下 2.web.xml配置 <web-app xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xmlns"http://java.sun.com/xml/ns/javaee" xsi:schemaLocation" http://java.sun.com/xml/ns/javaee http://jav…

CSS3 选择前几个元素 选择后几个元素等问题

//例如有如下代码块 <div><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p> </div>1.选择第n个p div:nth-child(n) p:nth-of-type(n)2.选择倒数第n…

[vue-cli] vue-cli中你经常的加载器有哪些?

[vue-cli] vue-cli中你经常的加载器有哪些&#xff1f; style,css,vue,postcss,url等个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

Python中将array类型不按科学计数法存在文件中的方法

直接上代码&#xff1a; from numpy import *import numpy as npDrug_array zeros((708,708),dtype int)f open(D:\mat_drug_drug.txt)lines f.readlines()Drug_row 0for line in lines: list line.strip(\n).split( ) Drug_array[Drug_row:] list[:] Drug_row…

[vue-cli] 你知道什么是脚手架吗?

[vue-cli] 你知道什么是脚手架吗&#xff1f; vue项目一般是使用webpack进行打包构建的&#xff0c;然而如果每一个项目都需要我们去配置loader和plugin的话&#xff0c;是很重复的劳动&#xff0c;并且vue项目需要使用到的最基本的webpack loader和webpack plugin是相同的。因…

Vue报错:Elements in iteration expect to have ‘v-bind:key‘ directives的解决办法

1.我们在使用v-for的时候&#xff0c;在v-for 后添加 v-bind:key"ite Vue 2.2.0的版本里&#xff0c;当在组件中使用v-for时&#xff0c;key是必须的。 1.我们在使用v-for的时候&#xff0c;在v-for 后添加 v-bind:key"item" <div v-for"todo in to…