首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC++

使用 IPHLPAPI 取得網卡詳細資訊:完整 C++ 原始碼範例

     編輯:VC++

前言

Windows 提供 IPHLPAPI.DLL 中的 GetAdaptersInfo 函式,可擷取本機所有網路介面卡的完整設定資訊,包括 MAC 位址、IP/子網路遮罩、預設閘道、DHCP/WINS 伺服器、租約時間等。本文提供可直接編譯執行的完整原始碼,並說明關鍵結構體與欄位含義。

必要標頭檔與連結庫

#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#pragma comment(lib, "iphlpapi.lib")

核心流程三步驟

  1. 第一次呼叫 GetAdaptersInfo 傳入 NULL 取得所需緩衝區大小(ERROR_BUFFER_OVERFLOW 為預期回傳)。
  2. 配置記憶體(GlobalAlloc(GPTR, size))。
  3. 第二次呼叫 GetAdaptersInfo 填入實際資料,遍歷 PIP_ADAPTER_INFO 連結列表輸出結果。

完整原始碼

void main(void) {
    DWORD dwErr;
    PIP_ADAPTER_INFO pAdapterInfo = NULL, pCurr = NULL;
    ULONG ulSize = 0;

    // 1. 取得所需緩衝區大小
    if ((dwErr = GetAdaptersInfo(NULL, &ulSize)) != ERROR_BUFFER_OVERFLOW) {
        printf("GetAdaptersInfo sizing failed: %lu\n", dwErr);
        return;
    }

    // 2. 配置記憶體
    pAdapterInfo = (PIP_ADAPTER_INFO)GlobalAlloc(GPTR, ulSize);
    if (!pAdapterInfo) {
        printf("Memory allocation failed\n");
        return;
    }

    // 3. 取得實際介面卡資訊
    if ((dwErr = GetAdaptersInfo(pAdapterInfo, &ulSize)) != NO_ERROR) {
        printf("GetAdaptersInfo failed: %lu\n", dwErr);
        GlobalFree(pAdapterInfo);
        return;
    }

    // 4. 遍歷並輸出每張網卡資訊
    for (pCurr = pAdapterInfo; pCurr; pCurr = pCurr->Next) {
        // 型別描述
        const char* szType = "Other";
        switch (pCurr->Type) {
            case MIB_IF_TYPE_ETHERNET: szType = "Ethernet"; break;
            case MIB_IF_TYPE_TOKENRING: szType = "Token Ring"; break;
            case MIB_IF_TYPE_FDDI: szType = "FDDI"; break;
            case MIB_IF_TYPE_PPP: szType = "PPP"; break;
            case MIB_IF_TYPE_LOOPBACK: szType = "Loopback"; break;
            case MIB_IF_TYPE_SLIP: szType = "SLIP"; break;
        }
        printf("\n%s Adapter %s:\n", szType, pCurr->AdapterName);
        printf("  Description : %s\n", pCurr->Description);
        
        // MAC 位址
        printf("  Physical Addr: ");
        for (UINT i = 0; i < pCurr->AddressLength; ++i) {
            printf("%02X%s", pCurr->Address[i], (i == pCurr->AddressLength-1) ? "\n" : "-");
        }

        printf("  DHCP Enabled : %s\n", pCurr->DhcpEnabled ? "Yes" : "No");

        // IP / Subnet / Gateway 列表
        PIP_ADDR_STRING pAddr = &pCurr->IpAddressList;
        while (pAddr) {
            printf("  IP Address   : %s\n", pAddr->IpAddress.String);
            printf("  Subnet Mask  : %s\n", pAddr->IpMask.String);
            pAddr = pAddr->Next;
        }
        pAddr = pCurr->GatewayList.Next;
        printf("  Def Gateway  : %s\n", pCurr->GatewayList.IpAddress.String);
        while (pAddr) {
            printf("               %s\n", pAddr->IpAddress.String);
            pAddr = pAddr->Next;
        }

        // DHCP / WINS / 租約時間
        printf("  DHCP Server  : %s\n", pCurr->DhcpServer.IpAddress.String);
        printf("  Primary WINS : %s\n", pCurr->PrimaryWinsServer.IpAddress.String);
        printf("  Secondary WINS: %s\n", pCurr->SecondaryWinsServer.IpAddress.String);

        time_t tLeaseObtained = pCurr->LeaseObtained;
        time_t tLeaseExpires  = pCurr->LeaseExpires;
        printf("  Lease Obtained: %s", ctime(&tLeaseObtained));
        printf("  Lease Expires : %s", ctime(&tLeaseExpires));
    }

    GlobalFree(pAdapterInfo);
}

關鍵結構體說明

  • IP_ADAPTER_INFO:每張網卡一個節點,透過 Next 形成單向連結列表。
  • IP_ADDR_STRING:IP/遮罩/閘道/DHCP/WINS 皆為此結構,支援多重 IP 設定。
  • LeaseObtained / LeaseExpires:time_t 格式,配合 ctime / gmtime 顯示人類可讀時間。

常見應用場景

  • 網路診斷工具自動掃描本機 IP 設定。
  • 軟體授權綁定 MAC 位址(Address 欄位)。
  • 偵測 DHCP 狀態、租約到期時間以實作網路監控代理程式。

注意事項

  • Windows Vista/7/8/10/11 建議改用 GetAdaptersAddresses(支援 IPv6、更完整的旗標),但 GetAdaptersInfo 仍相容保留。
  • 記憶體務必以 GlobalFree 釋放,避免洩漏。
  • 需連結 iphlpapi.lib,並確保專案設定包含 winsock2.h 在 windows.h 之前(避免衝突)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved