本文为 HinGwenWoong 原创,如果这篇文章对您有帮助,欢迎转载,转载请阅读文末的【授权须知】,感谢您对 HinGwenWoong 文章的认可!
随着物联网设备的增加,在一般场景中,使用 DHCP
可以更加快捷方便的让设备可以做到不同局域网都插上网线可以立刻使用。
我是 HinGwenWoong ,一个有着清晰目标不停奋斗的程序猿,热爱技术,喜欢分享,码字不易,如果帮到您,请帮我在屏幕下方点赞 ,您的点赞可以让技术传播得更远更广,谢谢!
DHCP
(Dynamic Host Configuration Protocol,动态主机配置协议)通常被应用在大型的局域网络环境中,主要作用是集中的管理、分配IP
地址,使网络环境中的主机动态的获得IP
地址、Gateway
地址、DNS
服务器地址等信息,并能够提升地址的使用率。
DHCP
协议采用客户端/服务器模型,主机地址的动态分配任务由网络主机驱动。当DHCP
服务器接收到来自网络主机申请地址的信息时,才会向网络主机发送相关的地址配置等信息,以实现网络主机地址信息的动态配置。DHCP
具有以下功能:
IP
地址在同一时刻只能由一台DHCP
客户机所使用。DHCP
应当可以给用户分配永久固定的IP地址。DHCP
应当可以同用其他方法获得IP地址的主机共存(如手工配置IP地址的主机)。DHCP
服务器应当向现有的BOOTP客户端提供服务。DHCP
有三种机制分配IP地址:
自动分配方式(Automatic Allocation),DHCP
服务器为主机指定一个永久性的IP
地址,一旦DHCP
客户端第一次成功从DHCP
服务器端租用到IP
地址后,就可以永久性的使用该地址。
动态分配方式(Dynamic Allocation),DHCP
服务器给主机指定一个具有时间限制的IP
地址,时间到期或主机明确表示放弃该地址时,该地址可以被其他主机使用。
手工分配方式(Manual Allocation),客户端的IP
地址是由网络管理员指定的,DHCP
服务器只是将指定的IP地址告诉客户端主机。
三种地址分配方式中,只有动态分配可以重复使用客户端不再需要的地址。
DHCP
消息的格式是基于BOOTP(Bootstrap Protocol)
消息格式的,这就要求设备具有BOOTP
中继代理的功能,并能够与BOOTP
客户端和DHCP
服务器实现交互。BOOTP
中继代理的功能,使得没有必要在每个物理网络都部署一个DHCP
服务器。RFC 951
和RFC 1542
对BOOTP
协议进行了详细描述。
本项目使用的是 LAN8720
芯片,需要修改 PHY Address
为 0
为什么需要使用 Host Name
呢?
是因为真正的生产环境中,我们不使用 log
很难知道我们的设备到底是获取到哪个 IP
,我们将设备固定一个 Host Name
(我自己使用的是一个固定的开头加上芯片唯一ID
),使用 Ping
这个 Host Name
的方式就可以立刻知道设备的 IP 了,下面是开启 Host Name 的方式:
如果生成的工程中找不到 netbiosns.c
文件
需要下载 LWIP
的官方 SDK:lwIP - A Lightweight TCP/IP stack
我这里是 lwip 2.1.2 版本,选择你需要的版本进行下载
下载完成后,解压,里面可以看到这个文件夹 netbiosns
在外部完善一个 DHCP
初始化的函数:
/* bsp includes. */
#include "FreeRTOS.h"
#include "timers.h"
/* bsp includes. */
#include "lwip/dhcp.h"
#include "lwip/dns.h"
#include "lwip/apps/netbiosns.h"
/* bsp includes. */
#include "bsp_printlog.h"
// 最大 DHCP 次数,设置一个 大点的值
#define MAX_DHCP_COUNT (50000)
/*!
* @brief 封装 dhcp 接口
* 执行条件:无
*
* @retval: 无
*/
err_t bsp_dhcp(void)
{
struct dhcp *dhcp;
uint32_t over_time = 0;
struct netif *netif_p = netif_default;
if(netif_p == NULL)
{
return ERR_VAL;
}
/* Start DHCP negotiation for a network interface (IPv4) */
// dhcp_start(netif); //可以在这里写,将该函数 bsp_dhcp() 代替掉 lwip.c 原本已经存在的 dhcp_start() 函数
//设置计算机名 (测试方法: (1)ping 计算机名 (2)用浏览器访问 http://计算机名/)
netif_p->hostname = "THOSTP"; //设置 Host Name
netbiosns_init();
netbiosns_set_name(netif_p->hostname);
// 外部定义了 netif_default
while(!dhcp_supplied_address(netif_p))
{
over_time++;
print_log("dhcp_connect: DHCP discovering... for %d times\r\n", over_time);
if(over_time > MAX_DHCP_COUNT)
{
print_log("dhcp_connect: overtime, not doing dhcp\r\n");
return ERR_TIMEOUT;
}
vTaskDelay(pdMS_TO_TICKS(500));
}
dhcp = netif_dhcp_data(netif_p);
print_log("DHCP IP address: %s\n", ip4addr_ntoa(&dhcp->offered_ip_addr));
print_log("DHCP Subnet mask: %s\n", ip4addr_ntoa(&dhcp->offered_sn_mask));
print_log("DHCP Default gateway: %s\n", ip4addr_ntoa(&dhcp->offered_gw_addr));
#if LWIP_DNS
print_log("DHCP DNS Server: %s\n", ip4addr_ntoa(dns_getserver(0)));
#ifdef DNS_SERVER_ADDRESS
/* initialize default DNS server address */
ip_addr_t dnsserver;
DNS_SERVER_ADDRESS(&dnsserver);
dns_setserver(0, &dnsserver);
#endif /* DNS_SERVER_ADDRESS */
print_log("after set DHCP DNS Server: %s\n", ip4addr_ntoa(dns_getserver(0)));
#endif
print_log("dhcp_connect: DHCP success\r\n");
return ERR_OK;
}
如果想看 LWIP
的 LOG
信息,在 lwipopts.h
中 定义宏 LWIP DEBUG
,这个操作有可能会导致一些打印打不出来,我就是 dhcp_bind()
信息打不出来导致我一直以为失败,结果是没有打印,先不使用打印看看是否可以获取到 IP
,可以获取到就不用打开了
//开启 LWIP DEBUG
#define LWIP_DEBUG
#include "bsp_printlog.h"
#undef LWIP_PLATFORM_DIAG
#define LWIP_PLATFORM_DIAG(x) do {print_log x;} while(0)
//开启 lwip DHCP DEBUG
#define DHCP_DEBUG LWIP_DBG_ON
打印信息打印 DHCP
获取的 IP
信息:
使用同一局域网的电脑进入 cmd
的 ping
命令测试,可以使用 hostname
和 IP
分别测试,host name
我在上面的 DHCP初始化
函数中修改的:
以上是 STM32 + LWIP
如何 使用 DHCP
动态获取 IP
的全部内容,本文介绍了如何动态获取 IP
的一个方法,让嵌入式物联网设备能够在不同的局域网都可使用。
我是 HinGwenWoong ,一个有着清晰目标不停奋斗的程序猿,热爱技术,喜欢分享,码字不易,如果帮到您,请帮我在屏幕下方点赞 ,您的点赞可以让技术传播得更远更广,谢谢!
作者:HinGwenWoong
一个有着清晰目标不停奋斗的程序猿,热爱技术,喜欢分享,共同进步!
CSDN: HinGwenWoong
原文链接:【嵌入式实战】STM32+Lwip 实现 DHCP+HostName(超详细)