7、IP 配置与 DHCP:IpManager 设计、DHCP 客户端交互、静态 IP 配置

说到 Wi-Fi 连接,很多人以为只要把密码填对、关联上 AP 就完事了。其实不然。关联成功只是第一步,真正让手机能上网的,是 IP 配置这一步。你想想看,没有 IP 地址,数据包往哪儿发?

这一章,我们就来聊聊 Android 里 IP 配置的核心——IpManager。它负责管理 DHCP 客户端、处理静态 IP、监听网络状态变化。说白了,它就是 Wi-Fi 的「网络层管家」。

7.1 IpManager 的设计思路

我个人习惯把 IpManager 理解为「状态机 + 策略执行器」。它不直接发 DHCP 请求,而是协调各个模块完成 IP 获取。

它的核心职责有三块:

  • 管理 DHCP 客户端:启动、停止、重启 DHCP 流程
  • 处理静态 IP:当用户选择静态配置时,跳过 DHCP,直接设置 IP
  • 监听网络状态:当网络断开或配置变更时,重新触发 IP 获取

我在项目中遇到过一个问题:某些路由器 DHCP 响应特别慢,导致 IpManager 超时后直接走 fallback 逻辑,分配了一个 169.254.x.x 的链路本地地址。用户一看「已连接但无法上网」,投诉就来了。后来我们调整了超时时间,才解决。

核心设计原则:IpManager 不关心底层是 Wi-Fi 还是以太网,它只关心「如何拿到一个可用的 IP 配置」。

它的内部状态机大致如下:

IDLE → RUNNING → CONFIGURED → DISCONNECTED
  ↑         ↓
  └─────────┘

嗯,这里要注意:从 RUNNING 到 CONFIGURED 的转换,取决于 DHCP 成功或静态配置生效。如果 DHCP 失败,它会尝试重试,重试次数耗尽后才进入 DISCONNECTED。

7.2 DHCP 客户端交互

Android 的 DHCP 客户端经历过几次变迁。早期用的是 dhcpcd,后来换成了 netd 内置的 DHCP 实现。现在主流版本用的是 IpManager + DhcpClient 的组合。

交互流程是这样的:

  1. Wi-Fi 关联成功后,WifiStateMachine 通知 IpManager 开始配置
  2. IpManager 创建 DhcpClient 实例,发起 DHCP Discover
  3. DhcpClient 收到 Offer 后,发送 Request
  4. 收到 Ack 后,DhcpClient 把 IP、网关、DNS 等信息返回给 IpManager
  5. IpManager 调用 netd 设置 IP 地址和路由

我曾经调试过一个奇葩问题:DHCP 明明拿到了 IP,但手机就是上不了网。抓包一看,网关地址是 0.0.0.0。你想想看,网关都是零,数据包往哪儿发?后来发现是路由器固件有 bug,Ack 包里的 Option 3 字段丢了。嗯,这种问题只能靠抓包定位。

调试技巧:用 adb shell dumpsys wifi 可以查看当前 IP 配置状态。如果看到 DhcpState=FAILED,基本可以断定是 DHCP 环节出了问题。

7.3 静态 IP 配置

静态 IP 配置,说白了就是跳过 DHCP,直接告诉系统「IP 是多少、网关是谁、DNS 用哪个」。这在企业网络或固定场景下很常见。

IpManager 处理静态 IP 的路径很简单:

if (isStaticIp) {
    // 直接使用用户配置
    LinkProperties lp = new LinkProperties();
    lp.setLinkAddress(staticIpAddress);
    lp.setRoutes(staticGateway);
    lp.setDnsServers(staticDnsList);
    // 通知网络层
    notifyLinkPropertiesChanged(lp);
} else {
    // 走 DHCP
    startDhcpClient();
}

这里有个坑:静态 IP 配置时,网关和子网掩码必须匹配。我见过有人把 IP 设为 192.168.1.100,网关却填了 10.0.0.1,结果数据包根本发不出去。系统不会帮你校验这个,它只会照做。

注意事项:静态 IP 配置不会自动处理 DNS 冲突。如果你手动填了 DNS,但路由器也下发 DNS,系统会优先使用手动配置的。这一点和 DHCP 不同。

7.4 核心流程图

下面这张图展示了 IpManager 从启动到配置完成的完整流程。我建议你仔细看看,尤其是 DHCP 失败时的 fallback 路径。

IpManager IP 配置流程 Wi-Fi 关联成功 IpManager 启动 静态 IP? 直接设置 LinkProperties 启动 DhcpClient DHCP 成功? 应用 DHCP 配置 Fallback 链路本地地址 通知网络层配置完成

从图上你能看到,静态 IP 和 DHCP 是两条完全独立的路径。静态配置直接跳过网络交互,而 DHCP 则要经历完整的四次握手。如果 DHCP 失败,系统会分配一个 169.254.x.x 的链路本地地址——这其实是 IPv4 的「最后保底方案」。

7.5 避坑指南

最后,分享几个我踩过的坑:

  • DHCP 超时设置:默认超时是 30 秒,但在信号弱的环境下,30 秒可能不够。我建议根据实际场景调整,比如企业网络可以放宽到 60 秒。
  • 静态 IP 与 DHCP 冲突:如果同一个 IP 被 DHCP 分配给了另一台设备,就会发生 IP 冲突。Android 不会主动检测这个,需要上层应用或路由器做防护。
  • DNS 缓存问题:切换网络时,DNS 缓存不会自动清空。我曾经遇到过用户从公司网络切到家庭网络,结果 DNS 还解析着公司内网地址,导致部分应用无法访问。

个人建议:在开发 Wi-Fi 相关功能时,一定要把 IP 配置的日志打全。尤其是 DHCP 的交互日志,它能帮你快速定位是「连不上」还是「配不上」。

好了,这一章的内容就到这里。IP 配置看似简单,但涉及到的细节不少。理解了 IpManager 的设计思路,你就能更好地掌控 Wi-Fi 连接的「最后一公里」。


公众号:蓝海资料掘金营,微信deep3321