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;
}