getifaddrs函数用于获取linux系统所有网络接口的ip地址和子网掩码(存于ifa_netmask字段),但不提供网关信息;网关需额外解析/proc/net/route或使用netlink,且须将网关与对应接口的子网掩码配对使用。

Linux下用getifaddrs获取网关和子网掩码
Linux没有直接返回网关的系统调用,getifaddrs 是最可靠的方式——它能遍历所有网络接口,拿到每个接口的 IPv4 地址、子网掩码,再结合路由表找默认网关。注意:子网掩码在 ifa_netmask 字段里,但网关不在 ifaddrs 结构中,得额外读 /proc/net/route 或调用 netlink。
常见错误是只看 AF_INET 接口却忽略 IFF_UP 和 IFF_RUNNING 状态,导致拿到已断开或未启用的接口信息。另外,getifaddrs 返回的地址顺序不固定,不能假设 eth0 一定排第一。
- 先调用
getifaddrs(&ifaddr),遍历链表过滤出ifa_family == AF_INET且ifa_flags & IFF_UP - 用
inet_ntop(AF_INET, &((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr, buf, sizeof(buf))提取子网掩码字符串 - 解析
/proc/net/route:找Destination == 00000000且Flags & 0x0001(U 标志)的行,Gateway字段是小端十六进制,需翻转字节并转点分十进制(例如01000000→127.0.0.1)
Windows下用GetIpForwardTable2获取默认网关
Windows 的 GetIpForwardTable2 是推荐方式,它直接返回 IPv4/v6 路由表,比旧的 GetIpForwardTable 更稳定,且能跨多网卡正确识别默认路由(Metric 最小 + Destination 为 0.0.0.0/0)。子网掩码则从绑定的接口地址中提取,不是从路由表来。
容易踩的坑:忘记调用 FreeMibTable 导致内存泄漏;误把 NextHop 当成本地接口地址;或没检查 Row->DestinationPrefix.PrefixLength 是否为 0(即 /0 路由)就当成默认网关。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 调用
GetIpForwardTable2(AF_INET, &table),遍历table->NumEntries - 对每条
row,检查row->DestinationPrefix.PrefixLength == 0 && row->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr == 0 - 网关地址在
row->NextHop.Ipv4.sin_addr.s_addr;对应接口的子网掩码需另行调用GetIfEntry2或从GetAdaptersAddresses中匹配row->InterfaceLuid获取
跨平台时为什么不能只依赖 gethostbyname 或 getaddrinfo
gethostbyname 和 getaddrinfo 解析的是域名,不是本地网络配置。有人误以为查 "default" 或 "gateway" 就能拿到网关,实际会失败或返回随机 DNS 结果。子网掩码更完全不在这两个函数的能力范围内。
另一个典型误区是尝试用 system("ip route | grep default") 或 system("route print") 解析命令输出——看似简单,但 shell 命令依赖环境、权限和语言 locale,输出格式易变(如 Windows 的 route print 在不同版本中列数不同),极难健壮解析。
-
gethostbyname("gateway.local")不会返回路由器 IP,除非你本地 hosts 文件明确写了这一行 - 执行
ip route时若进程无 CAP_NET_ADMIN 权限,在某些容器或受限环境中会报错RTNETLINK answers: Operation not permitted - 即使命令成功,解析第 3 列(Linux)或“网关”列(Windows)也需要正则或字段切分,而空格、中文、IPv6 地址会让逻辑崩坏
子网掩码和网关必须配对使用才有意义
拿到一个网关 IP 却不知道它属于哪个子网,基本无法用于实际判断(比如判断某 IP 是否在同一局域网)。反过来,只有子网掩码没有网关,也做不了路由决策。两者必须来自同一接口上下文——例如 eth0 的子网掩码和通过 eth0 达到的默认网关,不能混用 wlan0 的掩码和 eth0 的网关。
真实场景中,多网卡机器(有线+WiFi+Docker bridge)可能有多个默认路由,此时应优先选 Metric 最小的那条,而不是第一个找到的。Linux 的 /proc/net/route 没有显式 Metric 字段,得靠 metric 列(第 8 列);Windows 的 GetIpForwardTable2 表里 row->Metric 直接可用。
- 不要把
192.168.1.1(网关)和255.255.0.0(错误掩码)组合,这会导致192.168.100.5被误判为不可达 - IPv6 环境下,
::作为 Destination 的路由才是默认路由,对应网关是NextHop字段,子网掩码概念替换为PrefixLength(通常为 128 或 64) - 虚拟网卡(如 VMware、Hyper-V、WSL2)常带独立路由,若业务逻辑只关心物理网络,需按
InterfaceLuid或接口描述符过滤
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










