跨平台网络接口枚举问询:GLib/GIO是否提供对应跨平台层?
用GLib/GIO实现跨平台网络接口枚举
既然你已经在大量使用GLib/GIO,那完全不用纠结原生API还是自己折腾跨平台层——GIO已经为你封装好了一套完美的跨平台网络接口枚举方案,直接用就行,完全兼容Linux和MinGW64环境,还能轻松拿到IPv4/IPv6地址及子网掩码。
核心优势
- 无缝集成你现有GLib/GIO代码,不用写一堆
#ifdef分支处理Linux和Windows的底层差异 - 直接封装了接口的所有关键信息:名称、状态、IPv4/IPv6地址、子网掩码(前缀长度转掩码也有现成方法)
- 维护成本低,GLib官方会处理不同系统的API变更,你不用自己跟进
代码示例
下面是一个完整的示例,能枚举所有网络接口的IPv4/IPv6地址和子网掩码:
#include <gio/gio.h> int main(int argc, char *argv[]) { // 初始化GLib g_type_init(); // 获取默认的网络监视器 GNetworkMonitor *monitor = g_network_monitor_get_default(); // 获取所有网络接口列表 GList *interfaces = g_network_monitor_get_network_interfaces(monitor); g_print("枚举本地网络接口:\n"); g_print("====================================\n"); // 遍历每个接口 for (GList *l = interfaces; l != NULL; l = l->next) { GNetworkInterface *iface = G_NETWORK_INTERFACE(l->data); const gchar *iface_name = g_network_interface_get_name(iface); const gchar *iface_display = g_network_interface_get_display_name(iface); g_print("接口名称: %s | 显示名称: %s\n", iface_name, iface_display); // 获取接口的所有地址(带子网掩码) GList *addresses = g_network_interface_get_addresses(iface); for (GList *a = addresses; a != NULL; a = a->next) { GInetAddressMask *mask = G_INET_ADDRESS_MASK(a->data); GInetAddress *addr = g_inet_address_mask_get_address(mask); gint prefix = g_inet_address_mask_get_prefix(mask); // 区分IPv4和IPv6 if (g_inet_address_get_family(addr) == G_SOCKET_FAMILY_IPV4) { g_print(" IPv4地址: %s/%d (子网掩码: %s)\n", g_inet_address_to_string(addr), prefix, g_inet_address_mask_to_string(mask)); } else if (g_inet_address_get_family(addr) == G_SOCKET_FAMILY_IPV6) { g_print(" IPv6地址: %s/%d (子网前缀: %s)\n", g_inet_address_to_string(addr), prefix, g_inet_address_mask_to_string(mask)); } } // 清理地址列表 g_list_free_full(addresses, g_object_unref); g_print("------------------------------------\n"); } // 清理接口列表 g_list_free_full(interfaces, g_object_unref); g_object_unref(monitor); return 0; }
编译与运行
- Linux:确保安装了GLib/GIO开发包,用以下命令编译:
gcc -o enum_interfaces enum_interfaces.c `pkg-config --cflags --libs gio-2.0` - MinGW64:先安装MinGW版本的GLib/GIO(比如通过MSYS2的
mingw-w64-x86_64-glib2包),然后用同样的命令编译(注意在MSYS2的MinGW64 shell中执行)。
关键API说明
g_network_monitor_get_default():获取系统默认的网络监视器实例,是入口点g_network_monitor_get_network_interfaces():返回所有活跃(或已配置)的网络接口列表,每个元素是GNetworkInterface对象g_network_interface_get_addresses():返回接口的所有地址条目,每个条目是GInetAddressMask——这个类直接封装了IP地址和子网前缀长度,不用自己计算掩码g_inet_address_mask_to_string():直接生成带掩码的字符串(比如192.168.1.100/24或2001:db8::1/64),如果需要单独的掩码字符串,也可以通过前缀长度计算(GIO也提供了相关工具函数)
对比原生API的好处
如果你自己用getifaddrs(Linux)和GetAdaptersAddresses(Windows),需要处理:
- 不同系统的结构体差异(比如
ifaddrsvsIP_ADAPTER_ADDRESSES) - IPv6地址的解析和格式化
- 子网掩码的转换(Windows返回的是掩码数组,Linux返回的是前缀长度)
- 大量的
#ifdef分支代码
而用GIO的话,这些细节都被封装好了,你只需要专注于业务逻辑,代码可读性和可维护性高很多。
内容的提问来源于stack exchange,提问作者eudoxos




