Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
dhcp
DHCP原理及使用介绍
发布于 2021-08-26 23:15:54 浏览:1231
订阅该版
[tocm] # 什么是DHCP 动态主机配置协议DHCP(Dynamic Host Configuration Protocol)是一种对基于TCP/IP协议主机的网络参数进行动态配置和集中管理的协议,可以实现: - 为网络主机分配IP地址。 DHCP可以提供两种地址分配机制,网络管理员可以根据网络需求为不同的主机选择不同的分配策略。 动态分配机制: 通过DHCP为主机分配一个有使用期限(这个使用期限通常叫做租期)的IP地址。这种分配机制适用于主机需要临时接入网络或者空闲地址数小于网络主机总数且主机不需要永久连接网络的场景。例如,企业出差员工的便携机、咖啡厅的移动终端为了临时接入网络需要获取IP地址。 静态分配机制: 网络管理员通过DHCP为指定的主机分配固定的IP地址。这种分配机制适用于对IP地址有特殊要求的主机,例如企业的文件服务器由于需要对外网用户提供服务,需要使用固定的IP地址。相比手工静态配置IP地址,通过DHCP方式静态分配机制避免人工配置发生错误,方便管理员统一维护管理。 - 为网络主机提供除IP地址以外的网络参数。 例如DNS服务器的IP地址、路由信息、网关地址等。 DHCP也是一种基于客户端/服务器模型的协议。DHCP服务器上不需要手工记录网络中所有主机MAC地址和IP地址的对应关系,而是通过地址池管理可供某网段主机使用的IP地址。 当主机成功向DHCP服务器申请到IP地址后,DHCP服务器才会记录主机MAC地址和IP地址的对应关系,且此过程不需要人工参与。同时,DHCP服务器还可以为某个网段内主机动态分配相同的网络参数,例如,缺省网关、DNS服务器的IP地址等。 DHCP可以把同一个地址在不同时间分配给不同的主机,当主机不需要使用地址时,可以释放此地址,供其他主机使用,从而实现了IP地址的重复利用。 - DHCP的优点 1、降低网络接入成本: 2、降低主机配置成本: 3、提高IP地址利用率: 4、方便统一管理: # DHCP报文格式及实现原理 ## 报文格式 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/25e53f2d8741462bd6f02cb75033b559.png.webp) 括号里的数字表示字段的长度,单位是字节 | 报文名称 | 说明 | | :--------- | :--: | | DHCP DISCOVER | DHCP客户端首次登录网络时进行DHCP交互过程发送的第一个报文,用来寻找DHCP服务器。 | | DHCP OFFER | DHCP服务器用来响应DHCP DISCOVER报文,此报文携带了各种配置信息。 | | DHCP REQUEST | 此报文用于以下三种用途。1、客户端初始化后,发送广播的DHCP REQUEST报文来回应服务器的DHCP OFFER报文。2、客户端重启后,发送广播的DHCP REQUEST报文来确认先前被分配的IP地址等配置信息。3、当客户端已经和某个IP地址绑定后,发送DHCP REQUEST单播或广播报文来更新IP地址的租约。 | | DHCP ACK | 服务器对客户端的DHCP REQUEST报文的确认响应报文,客户端收到此报文后,才真正获得了IP地址和相关的配置信息。 | | DHCP NAK | 服务器对客户端的DHCP REQUEST报文的拒绝响应报文,例如DHCP服务器收到DHCP REQUEST报文后,没有找到相应的租约记录,则发送DHCP NAK报文作为应答,告知DHCP客户端无法分配合适IP地址。 | | DHCP DECLINE | 当客户端发现服务器分配给它的IP地址发生冲突时会通过发送此报文来通知服务器,并且会重新向服务器申请地址。 | | DHCP RELEASE | 客户端可通过发送此报文主动释放服务器分配给它的IP地址,当服务器收到此报文后,可将这个IP地址分配给其它的客户端。 | | DHCP INFORM | DHCP客户端获取IP地址后,如果需要向DHCP服务器获取更为详细的配置信息(网关地址、DNS服务器地址),则向DHCP服务器发送DHCP INFORM请求报文。 | - DHCP报文中的Options字段 DHCP报文中的Options字段可以用来存放普通协议中没有定义的控制信息和参数。如果用户在DHCP服务器端配置了Options字段,DHCP客户端在申请IP地址的时候,会通过服务器端回应的DHCP报文获得Options字段中的配置信息。 Options字段的格式如下图1所示。 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/327f70b1378aca4629afecf1b185f482.png) Options字段由Type、Length和Value三部分组成。这三部分的表示含义如下所示: | 字段 | 长度 | 含义 | | :--------- | :--: | -----------: | | Type | 1字节 | 该字段表示信息类型。 | | Length | 1字节 | 该字段表示后面信息内容的长度。 | | Value | 其长度为Length字段所指定 | 该字段表示信息内容。 | DHCP Options选项的取值范围为1~255,如下表2所示,介绍DHCP Options的部分知名选项 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/cac1daa0c497950c01711b5bab57259b.png.webp) ![image.png](https://oss-club.rt-thread.org/uploads/20210826/c3e10656f035cd52a79694e2b5ad73ef.png.webp) ## 实现原理 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/b05fb2a92f7a9505ff36897badb7f0a4.png.webp) ![image.png](https://oss-club.rt-thread.org/uploads/20210826/f54fe7250de10beb65edb74788f1109d.png) - 发现阶段 DHCP客户端在网络中广播发送DHCP DISCOVER请求报文,发现DHCP服务器,请求IP地址租约 - 提供阶段 DHCP服务器通过DHCP OFFER报文向DHCP客户端提供IP地址预分配 - 选择阶段 DHCP客户端通过DHCP REQUEST报文确认选择第一个DHCP服务器为它提供IP地址自动分配服务 - 确认阶段 被选择的DHCP服务器通过DHCP ACK报文把在DHCP OFFER报文中准备的IP地址租约给对应DHCP客户端 关于DHCP的内容还是比较多的,仅仅做了一些简单介绍 # rt-thread中使用DHCP功能 本次基于env环境搭建工程,基于STM32F407开发板,LAN8720网口 现在gitbub down下来rt-thread的bsp包, 进去到探索者的BSP包,右击选择comEmu Here ![image.png](https://oss-club.rt-thread.org/uploads/20210826/58a4d3da567d6789c0b84f2433e5d047.png) 在弹出的env操作框中输入menuconfig,添加网络组件 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/8d8839e757714686270910a4c5b0e93b.png) rt-thread Configuration-->rt-Thread Components-->Network 进入到网络组件 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/b2a9f0a27a59ebbddb4343b8aeec6f36.png) Socket abstraction layer 默认选项即可 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/4891e22912ed180065d023e64797a077.png) Network interface device 除了IPV6,都选上 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/d760914ebe21bcaeb706cb7f36ebe590.png) light weight tcp/ip stack 这个里面内容比较多,根据自己的需要选择相应的功能即可,本次我们测试DHCP功能,选择DHCP功能 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/2a00fabbef446c90e69f3667581bcc0c.png) 退出保存即可 接下来我们使用keil5编译工程,在env环境输入scons --target=keil5,生成keil5环境的工程,如果你用IAR,换成IAR即可,编译完成,此时我们就可以到熟悉的keil5环境中操作了 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/8d355d188d091f0a9001310948e7e92e.png) 关于DHCP的代码已经添加进来了,编译下载,看看效果 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/e0c01560f3fa12e68a42638d262a18d3.png) 需要注意的是,需要经过路由器连接,电脑连接路由器,开发板网口也连接路由器,输入ifconfig,发现已经自动获取到IP地址啦 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/ff45f274def1bff1913310365a56d740.png) 接下来ping一下我们的主机 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/7b3c4620f7586e2c37622715fe2e377d.png) 礼尚往来,主机ping一下我们的开发板 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/218572441b6327f3e0930e15e9e59cf2.png) 挺好... 接下来,我们把开发板作为客户端,与主机(网络调试助手)进行通讯 添加一下函数 ```java /**===================tcpclient=====================*/ #define BUFSZ 512 static void tcpclient(int argc, char **argv) { int ret; char *recv_data; struct hostent *host; int sock, bytes_received; struct sockaddr_in server_addr; const char *url; int port; if (argc < 3) { rt_kprintf("Usage:tcpclient URL PORT\n"); rt_kprintf("Like: tcpcilent 192.168.1.20 5000"); return; } url = argv[1]; port = strtoul(argv[2], 0, 10); host = lwip_gethostbyname(url); recv_data = rt_malloc(BUFSZ); if (recv_data == RT_NULL) { rt_kprintf("No memory\n"); return; } /* 创建一个 socket,类型是 SOCKET_STREAM,TCP 类型 */ if ((sock = lwip_socket(AF_INET, SOCK_STREAM, 0)) == -1) { /* 创建 socket 失败 */ rt_kprintf("Socket error\n"); /* 释放接收缓冲 */ rt_free(recv_data); return; } server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr = *((struct in_addr *)host->h_addr); rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); if (lwip_connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { rt_kprintf("Connect fail\n"); lwip_close(sock); rt_free(recv_data); return; } while (1) { bytes_received = lwip_recv(sock, recv_data, BUFSZ - 1, 0); if (bytes_received < 0) { lwip_close(sock); rt_kprintf("\n received error, close the socket.\r\n"); break; } else if (bytes_received == 0) { rt_kprintf("\n received warning, recv function return 0.\r\n"); continue; } recv_data[bytes_received] = '\0'; if (strncmp(recv_data, "q", 1) == 0 || strncmp(recv_data, "Q", 1) == 0) { lwip_close(sock); rt_kprintf("\n got a 'q' or 'Q', close the socket. \r\n"); rt_free(recv_data); break; } else { rt_kprintf("\n Receive data = %s", recv_data); } ret = lwip_send(sock, recv_data, strlen(recv_data), 0); if (ret < 0) { lwip_close(sock); rt_kprintf("\n send error, close the socket.\r\n"); rt_free(recv_data); break; } else if (ret == 0) { rt_kprintf("\n Send warning, send funcion returun 0. \r\n"); } } } MSH_CMD_EXPORT(tcpclient, tcpclient sample); ``` 网络调试助手作为服务器 PC端IPV4地址设置如下 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/7873d6f027e955d48c5944c1f841c842.png) 网络调试助手 ![image.png](https://oss-club.rt-thread.org/uploads/20210826/079835643e2d35dc160c9cf8ee877dc1.png) 控制台输入tcpclient 192.168.1.106 8080,连接成功,然后发送数据至网络调试助手,测试成功。over ![image.png](https://oss-club.rt-thread.org/uploads/20210826/219c20274bf8d83ec4646db3eae8235e.png)
1
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
Enthusiasm
公众号:小飞哥玩嵌入式
文章
8
回答
7
被采纳
0
关注TA
发私信
相关文章
1
disable dhcp后,网络会断开
2
关于WIZnet组件包里的wiz_dhcp_work函数
3
可以利用LWIP 实现DHCP和静态IP转换吗?
4
运行时 LWIP 切换DHCP 状态
5
ifconfig设置IP地址及网关出问题
6
w5500 无法获取到网络
7
lwip的DHCP续租
8
w5500 DHCP获取失败
9
开启DHCP获取的地址为什么都是0呢,哪里出了问题?
10
W5500 IP 续约会重新 DHCP_init() 的问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
机器人操作系统 (ROS2) 和 RT-Thread 通信
4
国产MCU移植系列教程汇总,欢迎查看!
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
LWIP
SPI
Env
Bootloader
AT
ART-Pi
Hardfault
CAN总线
FinSH
USB
文件系统
DMA
RT-Thread
SCons
线程
RT-Thread Nano
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
ota在线升级
WIZnet_W5500
I2C_IIC
UART
flash
cubemx
packages_软件包
freemodbus
潘多拉开发板_Pandora
PWM
定时器
ADC
BSP
中断
编译报错
socket
keil_MDK
GD32
MicroPython
msh
Debug
ulog
SFUD
flashDB
SDIO总线
rt_mq_消息队列_msg_queue
本月问答贡献
用户名由3_15位
19
个答案
3
次被采纳
踩姑娘的小蘑菇
16
个答案
3
次被采纳
xiaorui
7
个答案
3
次被采纳
sakumisu
5
个答案
3
次被采纳
三世执戟
32
个答案
1
次被采纳
本月文章贡献
比特饼干
3
篇文章
9
次点赞
Z_Y
2
篇文章
5
次点赞
xusiwei1236
2
篇文章
3
次点赞
yinxiangxv
2
篇文章
3
次点赞
Alipay
2
篇文章
3
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部