DHCP协议介绍
什么是DHCP?
动态主机配置协议DHCP(Dynamic Host Configuration Protocol)是一种网络管理协议,用于集中对用户IP地址进行动态管理和配置。
DHCP于1993年10月成为标准协议,其前身是BOOTP协议。DHCP协议由RFC 2131定义,采用客户端/服务器通信模式,由客户端(DHCP Client)向服务器(DHCP Server)提出配置申请,DHCP Server基于请求的客户端(DHCP Client)的mac地址为它动态分配IP地址、子网掩码、默认网关地址,域名服务器(DNS)地址和其他相关配置参数,以便可以与其他IP网络通信。
为什么要使用DHCP?
在IP网络中,每个连接Internet的设备都需要分配唯一的IP地址。DHCP使网络管理员能从中心结点监控和分配IP地址。当某台计算机移到网络中的其它位置时,能自动收到新的IP地址。DHCP实现的自动化分配IP地址不仅降低了配置和部署设备的时间,同时也降低了发生配置错误的可能性。另外DHCP服务器可以管理多个网段的配置信息,当某个网段的配置发生变化时,管理员只需要更新DHCP服务器上的相关配置即可,实现了集中化管理。
总体来看,DHCP相比设置静态IP地址带来了如下优势:
- 准确的IP配置:IP地址配置参数必须准确,并且在处理“ 192.168.XXX.XXX”之类的输入时,很容易出错。另外印刷错误通常很难解决,使用DHCP服务器可以最大程度地降低这种风险。
- 减少IP地址冲突:每个连接的设备都必须有一个IP地址。但是,每个地址只能使用一次,重复的地址将导致无法连接一个或两个设备的冲突。当手动分配地址时,尤其是在存在大量仅定期连接的端点(例如移动设备)时,可能会发生这种情况。DHCP的使用可确保每个地址仅使用一次。
- IP地址管理的自动化:如果没有DHCP,网络管理员将需要手动分配和撤消地址。跟踪哪个设备具有什么地址可能是徒劳的,因为几乎无法理解设备何时需要访问网络以及何时需要离开网络。DHCP允许将其自动化和集中化,因此网络专业人员可以从一个位置管理所有位置。
- 高效的变更管理:DHCP的使用使更改地址,范围或端点变得非常简单。例如,组织可能希望将其IP寻址方案从一个范围更改为另一个范围。DHCP服务器配置有新信息,该信息将传播到新端点。同样,如果升级并更换了网络设备,则不需要网络配置。
劣势:可能会导致同一设备的IP地址不固定,例如我们的服务器或者是一些设备想固定IP地址的话,这个时候就只能采取静态IP地址来配置了。
硬件准备
- W5500-EVB-Pico开发板
- 网线
- Micro USB数据线
注意:需将W5500-EVB-Pico通过RJ45网口接入到路由器上,电脑也接入到同一路由器下。路由器必须开启DHCP服务
软件环境
- Visual Studio Code
W5500-EVB-Pico使用DHCP协议获取IP地址
步骤1:找到dhcp_client示例程序并打开
添加“dhcp.h”头文件
#include "dhcp.h"
配置网络信息结构体内容,将.dhcp的内容设置为NETINFO_DHCP
//配置网络配置信息结构体
wiz_NetInfo net_info = {
.mac = {0x00, 0x08, 0xdc, 0x16, 0xed, 0x2e},
.ip = {192, 168, 1, 120},
.sn = {255, 255, 255, 0},
.gw = {192, 168, 1, 1},
.dns = {8, 8, 8, 8},
.dhcp = NETINFO_DHCP};
//DHCP初始化函数
static void dhcp_init(void)
{
printf(" DHCP client running \r\n");
DHCP_init(SOCKET_DHCP,ethernet_buf);
reg_dhcp_cbfunc(dhcp_assign,dhcp_assign,dhcp_conflict);
}
//IP地址冲突函数
static void dhcp_conflict(void)
{
printf("CONFLICT IP from DHCP\r\n");
while(1);
}
//请求IP地址函数
static void dhcp_assign(void)
{
getIPfromDHCP(net_info.ip);
getGWfromDHCP(net_info.gw);
getSNfromDHCP(net_info.sn);
getDNSfromDHCP(net_info.dns);
net_info.dhcp = NETINFO_DHCP;
network_initialize(net_info);
print_network_information(net_info);
printf("DHCP LEASED TIME:%ld Sec.\r\n",getDHCPLeasetime());
}
//定时器回调函数,目的是调用DHCP定时中断函数
bool repeating_timer_callback(struct repeating_timer *t) {
DHCP_time_handler();
return true;
}
//DHCP获取IP地址
void do_dhcp(void)
{
uint8_t retval = 0;
uint8_t dhcp_retry = 0;
if (net_info.dhcp == NETINFO_DHCP)
{
retval = DHCP_run();
if (retval == DHCP_IP_LEASED)
{
if (dhcp_get_ip_flag == 0)
{
printf("DHCP success\r\n");
dhcp_get_ip_flag = 1;
}
}
else if (retval == DHCP_FAILED)
{
dhcp_get_ip_flag = 0;
dhcp_retry++;
if (dhcp_retry <= DHCP_RETRY_COUNT)
{
printf(" DHCP timeout occurred and retry %d \r\n", dhcp_retry);
}
}
if (dhcp_retry > DHCP_RETRY_COUNT)
{
printf(" DHCP failed \r\n");
DHCP_stop();
while (true)
;
}
}
}
int main()
{
struct repeating_timer timer;//定义定时器结构体
stdio_init_all();//重定义串口到printf
sleep_ms(5000);
printf("W5500 network install example.\r\n");
wizchip_initialize();//spi接口初始化,链路初始化检测
add_repeating_timer_ms(1000, repeating_timer_callback, NULL, &timer);//
setSHAR(net_info.mac);
if (net_info.dhcp == NETINFO_DHCP)
{
dhcp_init();
}
else
{
network_initialize(net_info);
print_network_information(net_info);
}
while (true)
{
do_dhcp();
sleep_ms(1000);
}
}
步骤2:编译烧录
- 选择GCC arm-none-eabi编译链
- 选择编译项目为dhcp_client
- 点击Build进行编译
编译之后,按住boot按钮把开发板连接到电脑上,此时电脑将开发板识别为大容量存储器,我们将build/examples/dhcp_client文件夹下面的uf2文件拖入开发板的大容量存储器中,就烧录好了。
步骤3:验证测试
此时串口会打印获取到的IP地址信息,我们也能直接ping通获取到的IP地址
示例下载链接
链接:W5500-EVB-Pico示例
本期内容就分享到这里啦!觉得写的还不错的话给个关注鼓励一下吧!下期我们来讲讲如何通过DNS解析百度的域名地址。