Skip to content

LV040-DHCP与IP地址自动获取 ​

一、 IP 地址的两种来源 ​

1. 静态配置与 DHCP ​

设备刚接入网络时,它自己并不知道该用什么 IP。有两种做法:

方式谁决定地址优点缺点
静态配置人(写死或用命令行)地址可预测,环境不受服务器影响要手工维护,容易冲突或写错
DHCP 自动获取网络里的 DHCP 服务器即插即用,不冲突依赖服务器;地址不固定

家里的手机、电脑连 WiFi 都是第二种,所以从来不用配 IP;而本工程用的是第一种,地址写死在宏里。

2. 两种方式的取舍 ​

这两种方式没有优劣,只有"适合什么场景":

  • 静态配置适合"地址必须被外部知道"的场景。比如服务器、打印机、以及本工程的 Bootloader——PC 上的脚本得知道去连谁。
  • DHCP 适合"设备频繁加入离开、地址不必固定"的场景。比如咖啡厅的 WiFi、办公室的访客网络。

本工程选静态的完整理由见第五节。

二、 DHCP 在协议栈里的位置 ​

1. 跑在 UDP 上的应用层协议 ​

DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)本身是一个应用层协议,运行在 UDP 之上:

项值
传输层协议UDP
服务器端口67
客户端端口68
广播地址255.255.255.255

这里有个绕不开的循环:要靠 DHCP 拿 IP,可发 DHCP 报文本身又需要 IP。

2. "先有鸡还是先有蛋"的绕法 ​

解决办法是用特殊地址把这一步绕过去:

  • 源 IP 用 0.0.0.0("我还没有地址");
  • 目的 IP 用 255.255.255.255(有限广播,本网段所有设备);
  • 目的 MAC 用 FF:FF:FF:FF:FF:FF。

这三个值分别对应 LV010 第三节里提到的 0.0.0.0/8,以及 LV030 第三节里的广播地址。也就是说,ARP 与广播机制才是 DHCP 能起步的前提。

从这个角度看协议栈的依赖顺序很清楚:链路层收发包 → ARP / IP → UDP → DHCP,一层都不能跳。

三、 DORA 四步交互 ​

1. 四步各自做什么 ​

这四个步骤合称 DORA:

步骤名称方向内容
1DISCOVER(发现)客户端 → 广播"本网段有没有 DHCP 服务器?我需要一个地址"
2OFFER(提供)服务器 → 客户端"我这有个 192.168.16.100,要不要"
3REQUEST(请求)客户端 → 广播"我选定 192.168.16.100 了"
4ACK(确认)服务器 → 客户端"准了,租给你 24 小时",同时给出掩码、网关、DNS
DHCP 的 DORA 四步交互与租约

2. 第 3 步为什么还要广播 ​

有一个细节常被问:第 3 步为什么还要广播?

因为网络里可能有多台 DHCP 服务器,第 2 步它们可能都给了 OFFER。客户端选定其中一个后,必须广播一声让落选的那些把候选地址收回去,否则那些地址就被白白占住了。

3. 第 4 步之后的补充动作 ​

第 4 步之后,客户端还会用 ARP 检查一下这个地址有没有被占用(免费 ARP,见 LV030 第五节),确认没冲突才正式启用。这一步在实验室里遇到"地址冲突"告警时值得留个心眼。

四、 租约与续租 ​

1. DHCP 给的不只是一串 IP ​

一次 ACK 里会带回一整套参数,这正是"插上网线就能上网"的原因:

参数作用
IP 地址自己的地址
子网掩码判断同网段
默认网关跨网段时的第一站(见 LV015)
DNS 服务器域名 → IP 的解析服务器
租约时长这个地址能用多久

一次拿到全部参数,这正是 DHCP 相比"手工填四个框"的最大价值:它不只分配地址,还顺带把"这个网络该怎么走"一起告诉了你。

2. T1、T2 与租期 ​

DHCP 分配的地址是租给你的,不是永久给你:

时间点动作
到租期的 50%(T1)客户端单播给原服务器请求续租
到租期的 87.5%(T2)如果还没续上,广播找任意服务器
租期到必须停止使用该地址

这样做的目的是:设备离开网络后,地址能被回收再分配给别人,不至于浪费。

两个时间点的设计意图也不一样:T1 是"优先找原服务器"(保持地址稳定),T2 是"保底求助"(先保证不断网,哪怕换个服务器)。

五、 本工程为什么不用 DHCP ​

1. 三条理由 ​

这不是"实现不了",而是故意不要,原因有三层:

(1)内存预算紧。本工程 lwipopts.h 里 MEM_SIZE 只有 8 KB、PBUF_POOL_SIZE 只有 8 个,DHCP 需要额外的状态机与报文缓冲,而 LWIP_DHCP 宏被显式关掉了(dhcp.c 虽然编进工程,但被宏裁成了空实现)。

(2)地址必须可预测。Bootloader 的升级流程是"PC 上的脚本主动去连板子",脚本里写死了 192.168.16.30。如果地址是 DHCP 随机分配的,脚本根本不知道该连谁——这是嵌入式升级场景里最实际的理由。

(3)不需要长期在线。DHCP 的价值在"设备频繁加入离开的网络"。而这块板子是"插上线、升级、跳转 APP",全程几分钟,静态地址更简单可靠。

2. 产品里的常见做法 ​

那产品里怎么做?常见组合是**"静态地址 + 存到非易失存储"**:默认给一个出厂地址,需要改的时候由上位机下发新地址,写进外部 SPI Flash(本工程的 paramset / paramget 命令与 W25Q128 驱动就是为这类需求准备的)。

这条路线保留了静态地址"可预测"的优点,又避免了"改地址要重新编译烧录"的缺点。

3. 169.254 地址:DHCP 失败的标志 ​

如果 PC 设成了"自动获取 IP",而网络里根本没有 DHCP 服务器,PC 会退而求其次,自己挑一个 169.254.x.x 用(叫链路本地地址,Windows 上会提示"受限制的连接")。

这个地址段在同一链路上靠 ARP 还能互相通信,但不可路由(出不了本网段)。

排错意义很大:只要看到 PC 拿到 169.254 开头的地址,就说明"地址没配好",此时去 ping 板子必然不通——不用再看网线、交换机,直接回去手工填一个同网段 IP 即可。

六、 小结与参考资料 ​

1. 本篇小结 ​

  • IP 可以静态配置,也可以由 DHCP 自动分配;本工程用静态,理由是内存紧张、地址要可预测、不需要长期在线。
  • DHCP 是应用层协议,跑在 UDP 上(服务器 67 / 客户端 68),起步时用 0.0.0.0 和 255.255.255.255 绕开"没有 IP"的死循环。
  • DORA 四步:DISCOVER → OFFER → REQUEST → ACK;REQUEST 要广播是为了让落选的服务器回收地址。
  • DHCP 顺带下发掩码、网关、DNS;地址是"租"的,T1 找原服务器续租、T2 广播兜底。
  • PC 拿到 169.254.x.x 就是 DHCP 失败的标志,也是排查的起点。
  • 本工程 LWIP_DHCP = 0,dhcp.c 被宏裁成空实现,仅作源码对照。

2. 参考资料 ​


本文档由 markdowncli 技能辅助生成