You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C/C++编程检测Windows/Linux系统的活跃本地IP地址

检测Windows和Linux系统中的活跃本地IP(无互联网环境)

核心逻辑

活跃IP的本质是系统路由表中默认路由绑定的网卡对应的IP——系统会依据路由表选择数据包发送的网卡,该网卡的IP就是当前用于通信的活跃IP。


Linux平台实现

Linux下通过解析/proc/net/route路由表文件,找到默认路由对应的网卡,再匹配网卡获取IP。

步骤

  1. 读取/proc/net/route,筛选目标为00000000的默认路由条目。
  2. 提取该条目的网卡名称(如eth0、wlan0)。
  3. 用getifaddrs()遍历网卡列表,匹配名称后获取对应IPv4地址(排除回环地址127.0.0.1)。

示例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>

// 获取默认路由绑定的网卡名称
char* get_default_route_interface() {
    FILE* fp = fopen("/proc/net/route", "r");
    if (!fp) return NULL;

    char line[256], iface[32], dest[16];
    fgets(line, sizeof(line), fp); // 跳过表头
    while (fgets(line, sizeof(line), fp)) {
        sscanf(line, "%s %s", iface, dest);
        if (strcmp(dest, "00000000") == 0) {
            fclose(fp);
            return strdup(iface);
        }
    }
    fclose(fp);
    return NULL;
}

// 根据网卡名称获取对应IPv4地址
char* get_ip_by_interface(const char* iface) {
    struct ifaddrs *ifaddr, *ifa;
    if (getifaddrs(&ifaddr) == -1) return NULL;

    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr == NULL) continue;
        if (ifa->ifa_addr->sa_family == AF_INET && strcmp(ifa->ifa_name, iface) == 0) {
            struct sockaddr_in* addr = (struct sockaddr_in*)ifa->ifa_addr;
            char* ip = malloc(INET_ADDRSTRLEN);
            inet_ntop(AF_INET, &addr->sin_addr, ip, INET_ADDRSTRLEN);
            freeifaddrs(ifaddr);
            if (strcmp(ip, "127.0.0.1") != 0) return ip;
            free(ip);
        }
    }
    freeifaddrs(ifaddr);
    return NULL;
}

int main() {
    char* iface = get_default_route_interface();
    if (!iface) {
        printf("无法找到默认路由网卡\n");
        return 1;
    }
    char* active_ip = get_ip_by_interface(iface);
    if (active_ip) {
        printf("活跃本地IP: %s\n", active_ip);
        free(active_ip);
    } else {
        printf("无法获取网卡对应IP\n");
    }
    free(iface);
    return 0;
}

Windows平台实现

Windows下调用系统API获取路由表,找到默认路由对应的网卡LUID,再通过网卡信息匹配获取IP。

步骤

  1. 调用GetIpForwardTable2获取IPv4路由表,筛选目标前缀长度为0的默认路由。
  2. 提取路由条目的InterfaceLuid标识。
  3. 调用GetAdaptersAddresses遍历网卡,匹配InterfaceLuid后获取IPv4地址(排除回环)。

示例代码

#include <windows.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>

#pragma comment(lib, "iphlpapi.lib")

// 获取默认路由绑定的网卡LUID
NET_LUID get_default_route_interface_luid() {
    NET_LUID luid = {0};
    DWORD size = 0;
    GetIpForwardTable2(AF_INET, NULL, &size, FALSE, 0); // 先获取缓冲区大小
    MIB_IPFORWARD_TABLE2* table = (MIB_IPFORWARD_TABLE2*)malloc(size);
    if (!table) return luid;

    if (GetIpForwardTable2(AF_INET, table, &size, FALSE, 0) == NO_ERROR) {
        for (DWORD i = 0; i < table->NumEntries; i++) {
            MIB_IPFORWARD_ROW2* row = &table->Table[i];
            if (row->DestinationPrefix.PrefixLength == 0 && row->InterfaceIndex != 0) {
                luid = row->InterfaceLuid;
                break;
            }
        }
    }
    free(table);
    return luid;
}

// 根据网卡LUID获取对应IPv4地址
char* get_ip_by_interface_luid(NET_LUID luid) {
    DWORD size = 0;
    GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, NULL, NULL, &size); // 获取缓冲区大小
    IP_ADAPTER_ADDRESSES* adapters = (IP_ADAPTER_ADDRESSES*)malloc(size);
    if (!adapters) return NULL;

    if (GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, NULL, adapters, &size) == NO_ERROR) {
        IP_ADAPTER_ADDRESSES* adapter = adapters;
        while (adapter) {
            if (adapter->Luid.Value == luid.Value) {
                IP_ADAPTER_UNICAST_ADDRESS* addr = adapter->FirstUnicastAddress;
                while (addr) {
                    if (addr->Address.lpSockaddr->sa_family == AF_INET) {
                        struct sockaddr_in* ipv4 = (struct sockaddr_in*)addr->Address.lpSockaddr;
                        char* ip = malloc(INET_ADDRSTRLEN);
                        inet_ntop(AF_INET, &ipv4->sin_addr, ip, INET_ADDRSTRLEN);
                        free(adapters);
                        if (strcmp(ip, "127.0.0.1") != 0) return ip;
                        free(ip);
                    }
                    addr = addr->Next;
                }
            }
            adapter = adapter->Next;
        }
    }
    free(adapters);
    return NULL;
}

int main() {
    NET_LUID luid = get_default_route_interface_luid();
    if (luid.Value == 0) {
        printf("无法找到默认路由网卡\n");
        return 1;
    }
    char* active_ip = get_ip_by_interface_luid(luid);
    if (active_ip) {
        printf("活跃本地IP: %s\n", active_ip);
        free(active_ip);
    } else {
        printf("无法获取网卡对应IP\n");
    }
    return 0;
}

注意事项

  • 上述代码仅支持IPv4,如需适配IPv6,修改地址族参数为AF_INET6并调整对应结构体即可。
  • Linux下普通用户即可读取路由表,Windows下多数场景无需管理员权限。
  • 若系统存在多个默认路由,可增加筛选逻辑(如优先选择metric值最小的路由)。

内容的提问来源于stack exchange,提问作者FalsinSoft

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 13:57:33