程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> [Win32]本地計算機網絡信息的獲取

[Win32]本地計算機網絡信息的獲取

編輯:C++入門知識

print?// getNativeComputerNetInformation.cpp  
/* 
在網絡編程中,服務器端需要知道本機的IP;唯一標識一台機器的MAC地址;
 
功能的實現都非常簡單,有五種函數可以直接調用:
1.用於獲取本地網絡適配器信息的函數:
DWORD GetAdaptersInfo( PIP_ADAPTER_INFO pAdapterInfo,  PULONG pOutBufLen );
2.用於獲取本地主機名、域名和DNS服務器信息的函數:
DWORD GetNetworkParamsInfo(PFIXED_INFO pFixedInfo, PULONG pOutBufLen );
3.用於獲取本地計算機網絡接口數量的函數
DWORD GetNumberOfInterfaces(PDWORD pdwNumIf);
4.用於獲取本地主機名、域名和DNS服務器信息的函數
DWORD GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable,         PULONG dwOutBufLen );
5.獲取本地計算機IP地址表的函數
DWORD GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder );
*/ 
#include <stdio.h>  
#include <WinSock2.h>  
#include <iphlpapi.h>  
 
#pragma comment(lib, "IPHLPAPI.lib")  
#pragma comment(lib, "ws2_32.lib")  
 
void main() 

// 各類函數聲明  
    int GetAdaptersInfoFunction();          // 獲取本地網絡適配器信息的函數  
    int GetNetworkParamsFunction();         // 獲取本地主機名、域名和DNS服務器信息  
    int GetInterfacesFunction();            // 獲取本地計算機網絡接口的基本信息  
    int GetIpAddrTableFunction();           // 獲取本地計算機的IP地址  
     
// 各類函數調用  
    char choice; 
    do{ 
        system("cls"); 
        printf("1.獲取本地網絡適配器信息的函數 GetAdaptersInfoFunction();\n"); 
        printf("2.獲取本地主機名、域名和DNS服務器信息 GetNetworkParamsFunction();\n"); 
        printf("3.獲取本地計算機網絡接口的基本信息 GetInterfacesFunction();\n"); 
        printf("4.獲取本地計算機的IP地址 GetIpAddrTableFunction();\n"); 
        printf("0.退出程序\n"); 
        printf("請輸入需要調用的函數:"); 
        scanf("%c", &choice); 
        printf("\n\n"); 
        switch(choice){ 
            case '0': break; 
            case '1':   GetAdaptersInfoFunction(); break; 
            case '2': GetNetworkParamsFunction(); break; 
            case '3': GetInterfacesFunction(); break; 
            case '4': GetIpAddrTableFunction(); break; 
            default: break; 
        } 
    }while('0' != choice);    

     
 
/**
 * 用於獲取本地網絡適配器信息的函數:
 * DWORD GetAdaptersInfo(
 *   _in PIP_ADAPTER_INFO pAdapterInfo;    // 結構體保存獲取到的網絡適配器的信息
 *   _out PULONG pOutBufLen                // 保存pAdapterInfo緩沖區的大小
 * );
 *
 * 網絡適配器的信息的結構體:網卡信息有:網卡名,網卡描述,MAC地址,網卡IP,網卡默認網關等
 * typedef struct _IP_ADAPTER_INFO {
 *   struct _IP_ADAPTER_INFO* Next;                 // 指定網絡適配器鏈表中的下一個網絡適配器;由於一台電腦可能有多個網卡,所以是鏈表結構
 *   DWORD ComboIndex;                              // 預留變量
 *   char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4]; // 網絡適配器的名稱
 *   char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];  // 網絡適配器的描述信息
 *   UINT AddressLength;                            // 網絡適配器MAC的長度
 *   BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];      // 網絡適配器的MAC地址
 *   DWORD Index;                                   // 網絡適配器索引(重啟計算機會改變的值)
 *   UINT Type;                                     // 網絡適配器的類型
 *   UINT DhcpEnabled;                              // 指定該網絡適配器上是否啟用了DHCP
 *   PIP_ADDR_STRING CurrentIpAddress;              // 預留變量
 *   IP_ADDR_STRING IpAddressList;                  // 與此網絡適配器上相關聯的IP地址列表
 *   IP_ADDR_STRING GatewayList;                    // 該網絡適配器上定義的IP地址的默認網關
 *   IP_ADDR_STRING DhcpServer;                     // 該網絡適配器上定義的DHCP服務器的IP地址
 *   BOOL HaveWins;                                 // 標明該網絡適配器是否啟用了WINS
 *   IP_ADDR_STRING PrimaryWinsServer;              // 主WIN服務器的IP地址
 *   IP_ADDR_STRING SecondaryWinsServer;            // 從WINS服務器的IP地址
 *   time_t LeaseObtained;                          // 當前的DHCP租借獲取的時間,只有在啟用DHCP時生效
 *   time_t LeaseExpires;                           // 當前的DHCP租借失敗的時間,只有在啟用DHCP時生效
 * } IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;
 
 
 typedef struct _IP_ADDR_STRING {   //存儲一個IP地址和其相應的子網掩碼,同時作為點分十進制的字符串
 struct _IP_ADDR_STRING* Next; //由於一個網卡可能有多個IP,故為鏈表結構
 IP_ADDRESS_STRING IpAddress;
 IP_MASK_STRING IpMask;
 DWORD Context;
 } IP_ADDR_STRING, *PIP_ADDR_STRING;
 
 typedef struct {            //存儲一個IP地址,同時作為點分十進制的字符串
 char String[4 * 4];
 } IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;
 
 **/ 
//一台機器上可能不止有一個網卡,但每一個網卡只有一個MAC地址,而每一個網卡可能配置多個IP地址;如平常的筆記本電腦中,就會有無線網卡和有線網卡兩種;因此,如果要獲得本機所有網卡的IP和MAC地址信息,則必須順序獲得每個網卡,再依次獲取其信息;   
int GetAdaptersInfoFunction()   // 獲取本地網絡適配器信息的函數  

// 變量聲明   
    IP_ADAPTER_INFO *pAdapterInfo;  // 指定獲取到的網絡信息結構體鏈表的指針  
    ULONG ulOutBufLen;              // 獲取到網絡信息結構體鏈表的長度  
    DWORD dwRetVal;                 // 返回調用編碼  
 
// 獲取本地網絡適配器的信息  
    // 為pAdapterINfo分配空間  
    pAdapterInfo = (IP_ADAPTER_INFO *) malloc(sizeof(IP_ADAPTER_INFO)); 
    ulOutBufLen = sizeof(IP_ADAPTER_INFO); 
    // 需要兩次調用GetAdaptersInfo()函數  
    // 第1次調用GetAdaptersInfo(), 獲取返回結果的大小保存到ulOutBufLen中  
    // 因為網絡信息結構體鏈表的默認長度是不知道的  
    if(ERROR_SUCCESS != GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) ){ 
        free(pAdapterInfo); 
        pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen); 
    } 
    // 第2次調用GetAdaptersInfo(), 獲取本地網絡信息保存到結構體pAdapterInfo中  
    if(ERROR_SUCCESS != (dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen))){ 
        printf("GetAdaptersInfo Error! &d\n", dwRetVal); 
        exit(1); 
    } 
 
    // 顯示本地網絡適配器信息,從pAdapterInfo獲取並顯示本地網絡信息  
    PIP_ADAPTER_INFO pAdapter; 
    pAdapter = pAdapterInfo; 
    while(pAdapter){ 
        printf("網絡適配器名: \t\t%s\n", pAdapter->AdapterName); 
        printf("網絡適配器描述: \t%s\n\n", pAdapter->Description); 
        printf("MAC地址:\t\t"); 
        // 處理MAC地址  
        for(unsigned int i = 0; i < pAdapter->AddressLength; ++i){ 
            if(i == (pAdapter->AddressLength -1 ) ){ // 最後一次輸入換行  
                printf("%.2x\n", (int)pAdapter->Address[i]); 
            } 
            else{ 
                printf("%.2X-", (int)pAdapter->Address[i]);//x十六進制(x:會是a,b,c,d,e;X:會是A,B,C,D,E)  
            } 
        } 
        printf("IP地址: \t\t%s\n", pAdapter->IpAddressList.IpAddress.String); 
        printf("子網掩碼: \t\t%s\n", pAdapter->IpAddressList.IpMask.String); 
        printf("網關: \t\t\t%s\n", pAdapter->GatewayList.IpAddress.String); 
        printf("---------------\n"); 
        if(pAdapter -> DhcpEnabled){ // 指定該網絡適配器上是否啟用了DHCP(動態主機配置協議)  
            printf("啟用DHCP: \t\t是\n"); 
            printf("DHCP服務器: \t\t%s\n", pAdapter->DhcpServer.IpAddress.String); 
        } 
        else{ 
            printf("啟用DHCP: \t\t否\n"); 
        } 
        // 處理下一個網絡適配器  
        pAdapter = pAdapter -> Next; 
        if(pAdapter){ 
            printf("\n\n**************************************************************\n"); 
        } 
    } 
 
// 釋放資源  
    if(pAdapterInfo){ 
        free(pAdapterInfo); 
    } 
    
    printf("\n\n"); 
    system("pause"); 
    return 0; 

 
/**
 * 用於獲取本地主機名、域名和DNS服務器信息的函數:
 * DWORD GetNetworkParamsInfo(
 *   _out PFIXED_INFO pFixedInfo;    // 使用FIXED_INFO結構體保存獲取到的本地網絡參數的信息
 *   _in PULONG pOutBufLen           // 保存pFixedInfo緩沖區的大小
 * );
 *
 * 保存本地主機名、域名和DNS服務器信息的結構體:
 * typedef struct { 
 *  char HostName[MAX_HOSTNAME_LEN + 4];      // 本地計算機的主機名
 *  char DomainName[MAX_DOMAIN_NAME_LEN + 4]; // 本地計算機注冊到域的名稱
 *  PIP_ADDR_STRING CurrentDnsServer;         // 預留變量
 *  IP_ADDR_STRING DnsServerList;             // 指定本地計算機上定義的DNS服務器列表
 *  UINT NodeType;                            // 本地計算機的節點類型
 *  char ScopeId[MAX_SCOPE_ID_LEN + 4];       // DHCP域名
 *  UINT EnableRouting;                       // 指定本地計算機是否啟用了路由的功能
 *  UINT EnableProxy;                         // 指定本地計算機是否為ARP代理
 *  UINT EnableDns;                           // 指定本地計算機是否啟用了DNS
 * } FIXED_INFO, *PFIXED_INFO;
 **/ 
 
int GetNetworkParamsFunction() // 獲取本地主機名、域名和DNS服務器信息  
{        
// 聲明變量  
    FIXED_INFO * FixedInfo;     // 定義保存本地計算機網絡參數信息的結構體指針  
    ULONG    ulOutBufLen;       // 保存獲取到的本地計算機網絡參數信息結構體鏈表的長度  
    DWORD    dwRetVal;          // 調用GetNetworkParams()函數的返回值  
    IP_ADDR_STRING * pIPAddr;   // 保存所有DNS服務器的IP地址列表  
 
// 獲取信息  
     
    FixedInfo = (FIXED_INFO *) GlobalAlloc( GPTR, sizeof( FIXED_INFO ) );   // 為FixedInfo結構體分配內存空間  
    ulOutBufLen = sizeof( FIXED_INFO );         // 初始化ulOutBufLen變量值  
     
    // 第1次調用GetNetworkParams()函數,獲取返回結果的大小到ulOutBufLen中  
    if( ERROR_BUFFER_OVERFLOW == GetNetworkParams( FixedInfo, &ulOutBufLen ) ) { 
        GlobalFree( FixedInfo ); 
        FixedInfo = (FIXED_INFO *) GlobalAlloc( GPTR, ulOutBufLen ); 
    } 
 
    // 第2次調用GetNetworkParams()函數,以前面獲取的ulOutBufLen作為參數,  
    if ( dwRetVal = GetNetworkParams( FixedInfo, &ulOutBufLen ) != ERROR_SUCCESS) { 
        printf( "調用GetNetworkParams()函數失敗。返回值: %08x\n", dwRetVal ); 
    } 
    else { 
        printf( "主機名: %s\n", FixedInfo->HostName ); 
        printf( "域名: %s\n", FixedInfo->DomainName ); 
        printf("\n==========網絡信息==========\n");  
 
         // 生成節點類型字符串  
         char* NodeType;  
         switch(FixedInfo->NodeType){  
             case BROADCAST_NODETYPE:    NodeType = "Broadcase Node";  break;  
             case PEER_TO_PEER_NODETYPE: NodeType = "Peer to Peer Node";  break;  
             case MIXED_NODETYPE:   NodeType = "Mixed Node";  break;  
             case HYBRID_NODETYPE:  NodeType = "Hybrid Node"; break;  
             default:   NodeType = "Unknown Node";  break;  
         }  
 
        printf("節點類型...................:%d - %s\n", FixedInfo->NodeType, NodeType);  
        printf("是否啟用路由功能...........:%s\n", (FixedInfo->EnableRouting != 0) ? "是" : "否");  
        printf("是否啟用ARP代理功能........:%s\n", (FixedInfo->EnableProxy != 0) ? "是" : "否");  
        printf("是否啟用DNS服務器..........:%s\n", (FixedInfo->EnableDns != 0) ? "是" : "否");  
 
        printf( "\nDNS服務器列表:\n" ); 
        printf( "%s\n", FixedInfo->DnsServerList.IpAddress.String ); 
 
        pIPAddr = FixedInfo->DnsServerList.Next; 
        while ( pIPAddr ) { 
            printf( "\t%s\n", pIPAddr->IpAddress.String ); 
            pIPAddr = pIPAddr->Next; 
        } 
    } 
 
    printf("\n"); 
    system("pause");    
    return 0; 

 
/**
 * 用於獲取本地計算機網絡接口數量的函數
 * DWORD GetNumberOfInterfaces(
 *   _out PDWORD pdwNumIf
 * );
 *
 * 用於獲取本地主機名、域名和DNS服務器信息的函數
 * DWORD GetInterfaceInfo(
 *  _out PIP_INTERFACE_INFO pIfTable,   // 接受本地計算機網絡接口基本信息的結構體IP_INTERFACE_INFO
 *  _inout PULONG dwOutBufLen           // 接到數據的大小
 * );
 *
 typedef struct _IP_INTERFACE_INFO {
 LONG    NumAdapters;
 IP_ADAPTER_INDEX_MAP Adapter[1];
 } IP_INTERFACE_INFO,*PIP_INTERFACE_INFO;
 
 * 用於保存計算機網絡接口信息的結構體
 * typedfe struct _IP_ADAPTER_INDEX_MAP{
 *  ULONG Index;                     // 網絡適配器索引號
 *  WCHAR Name[MAX_ADAPTER_NAME];   // 網絡適配器名稱
 * }IP_INTERFACE_INDEX_MAP, *PIP_ADAPTER_INDEX_MAP; 
 **/ 
 
// 分配內存空間  
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))   
// 釋放內存空間  
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))  
 
int GetInterfacesFunction() // 獲取本地計算機網絡接口的基本信息  

// 獲取網絡接口的數量  
    DWORD dwNumIf;      // 用於獲取接口數量  
    DWORD  dwRetVal;    // 返回值  
    if(dwRetVal = GetNumberOfInterfaces(&dwNumIf) == NO_ERROR){ 
        printf("本地網絡接口數量為: %d\n", dwNumIf); 
    } 
    else{ 
        printf("調用GetNumberOfInterfaces()函數時出現錯誤。\n"); 
    } 
 
// 獲取網絡接口的基本信息  
    PIP_INTERFACE_INFO pInfo;   // 保存網絡接口信息的結構體指針  
    ULONG ulOutBufLen = 0;      // 保存獲取數據的長度  
    int iReturn = 1;            // 本函數的返回結果  
 
    // 第1次調用 GetInterfaceInfo,獲取數據大小,保存到ulOutBufLen變量中  
    dwRetVal = GetInterfaceInfo(NULL, &ulOutBufLen); 
    if (dwRetVal == ERROR_INSUFFICIENT_BUFFER) { 
        pInfo = (IP_INTERFACE_INFO *) MALLOC(ulOutBufLen); 
        if (pInfo == NULL) { 
            printf("無法分配GetInterfaceInfo函數需要的內存空間。\n"); 
            return 1; 
        } 
    } 
    // 第2次調用GetInterfaceInfo函數,獲取需要的實際數據  
    dwRetVal = GetInterfaceInfo(pInfo, &ulOutBufLen); 
    if (dwRetVal == NO_ERROR) { 
        printf("網絡適配器數量: %ld\n\n", pInfo->NumAdapters); 
        for (int i = 0; i < (int) pInfo->NumAdapters; i++) { 
            printf("網絡適配器索引[%d]: %ld\n", i, 
                   pInfo->Adapter[i].Index); 
            printf("網絡適配器名稱[%d]: %ws\n\n", i, 
                   pInfo->Adapter[i].Name); 
        } 
        iReturn = 0; 
    } else if (dwRetVal == ERROR_NO_DATA) { 
        printf 
            ("本地計算機上沒有支持IPv4的網絡適配器。\n"); 
        iReturn = 0; 
    } else { 
        printf("GetInterfaceInfo調用失敗: %d\n", dwRetVal); 
        iReturn = 1; 
    } 
     
    FREE(pInfo);    // 釋放內存空間  
    system("pause"); 
    return (iReturn); 

 
 
/** 
 * 獲取本地計算機IP地址表的函數
 * DWORD GetIpAddrTable(
 *   _out PMIB_IPADDRTABLE pIpAddrTable,  // 接受獲取到的本地計算機網絡接口和IP地址的映射表
 *   _inout PULONG pdwSize,               // 接收收到數據的大小
 *   _in BOOL bOrder                     // 獲取到的映射表中是否按IP地址的升序排列
 * );
 *
 * 用於保存IP地址表的PMIB_IPADDRTABLE結構體
 * typedef struct _MIB_IPADDRTABLE{
 *   DWORD      dwNumEntries;                   // 表示映射表中記錄的數量
 *   MIB_IPADDRROW table[ANY_SIZE];             // MIB_IPADDRROW結構體數組
 * }MIB_IPADDRTABLE, *PMIB_IPADDRTABLE;
 *
 * 用於保存IP地址的結構體
 * typedef struct _MIB_IPADDRROW{
 *   DWORD dwAddr;   // 網絡字節序格式的IP地址
 *   DWORD dwIndex;  // 與IP地址相關聯的網絡編號序號
 *   DWORD dwMask;   // 網絡字節序的子網掩碼
 *   DWORD dwBCastAddr;  // 網絡字節序格式的廣播地址
 *   DWORD dwReasmSize;  // 已收到的數據報重裝後的最大長度
 *   unsigned short unusedl;  // 預留字段
 *   unsigned short wType;    // IP地址的類型或狀態
 * }MIB_IPADDRROW, *PMIB_IPADDRROW;
 **/ 
 
//#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))  
//#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))  
 
int GetIpAddrTableFunction() 

    PMIB_IPADDRTABLE pIPAddrTable;  // 網絡接口與IP地址映射表  
    DWORD dwSize = 0;   // 獲取數據的大小  
    DWORD dwRetVal = 0; // 調用GetIPAddrTable()函數的返回值  
    IN_ADDR IPAddr;     // 保存IP地址的結構體  
    LPVOID lpMsgBuf;    // 用於獲取錯誤信息  
 
    // 分配內存空間  
    pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(sizeof (MIB_IPADDRTABLE)); 
    // 第1次調用GetIpAddrTable()函數,獲取數據的大小到dwSize  
    if (pIPAddrTable) { 
        if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) ==  ERROR_INSUFFICIENT_BUFFER) { 
            FREE(pIPAddrTable); 
            pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(dwSize); 
 
        } 
        if (pIPAddrTable == NULL) { 
            printf("GetIpAddrTable()函數內存分配失敗\n"); 
            exit(1); 
        } 
    } 
    // 第2次調用GetIpAddrTable()函數,獲取實際數據  
    if ( (dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 )) != NO_ERROR ) {  
        printf("GetIpAddrTable()調用失敗: %d\n", dwRetVal); 
        if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,  
                   dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) & lpMsgBuf, 0, NULL)) { 
            printf("\t錯誤信息: %s", lpMsgBuf); 
            LocalFree(lpMsgBuf); 
        } 
        exit(1); 
    } 
 
    printf("\t記錄數量: %ld\n", pIPAddrTable->dwNumEntries); 
    for (int i=0; i < (int) pIPAddrTable->dwNumEntries; i++) { 
        printf("\n\t接口序號[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex); 
        IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr; 
        printf("\tIP地址[%d]:     \t%s\n", i, inet_ntoa(IPAddr) ); 
        IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask; 
        printf("\t子網掩碼[%d]:    \t%s\n", i, inet_ntoa(IPAddr) ); 
        IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr; 
        printf("\t廣播地址[%d]:      \t%s (%ld%)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr); 
        printf("\t重組報文最大數量[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize); 
        printf("\t類型和狀態[%d]:", i); 
        if (pIPAddrTable->table[i].wType & MIB_IPADDR_PRIMARY)       printf("\t主IP地址"); 
        if (pIPAddrTable->table[i].wType & MIB_IPADDR_DYNAMIC)        printf("\t動態IP地址"); 
        if (pIPAddrTable->table[i].wType & MIB_IPADDR_DISCONNECTED)   printf("\t斷開連接的接口對應的IP地址"); 
        if (pIPAddrTable->table[i].wType & MIB_IPADDR_DELETED)        printf("\t刪除的IP地址"); 
        if (pIPAddrTable->table[i].wType & MIB_IPADDR_TRANSIENT)       printf("\t臨時地址"); 
        printf("\n"); 
    } 
 
    if (pIPAddrTable) { 
        FREE(pIPAddrTable); 
        pIPAddrTable = NULL; 
    } 
 
    printf("\n"); 
    system("pause"); 
    return 0; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved