Windows网络编程第六章探测网络中的在线设备
实验:获取本地计算机的网络信息
实验分析:主要练习对GetAdaptersInfo()、GetNetworkParams()、GetInterfaceInfo()、GetIPAddrTable()等API函数的运用,实验中需要注意的是需要两次调用该函数,第一次返回本机要调查信息的数量,第二次调用显示具体信息。
GetInfo.h
void pAdapter(); void Network(); void NumberOfInterfaces(); int GetIpAddr();
GetInfo.cpp
//********************声明头文件**************************** #include<iostream> #include<WinSock2.h> #include<IPHlpApi.h> #include<stdio.h> #pragma comment(lib,"ws2_32.lib") using namespace std; #pragma comment(lib,"IPHLPAPI.lib") //****************一、获取本地网络适配器信息*************** void pAdapter() { //声明变量 //指定获取到的网络信息结构体链表的指针 IP_ADAPTER_INFO *pAdapterInfo; //保存获取到的网络信息结构体链表的长度 ULONG ulOutBufLen; //返回调用编码 DWORD dwRetVal; //在轮循所有网络适配器信息时使用的单个结构体变量 PIP_ADAPTER_INFO pAdapter; //*******************获取本地网络适配器信息*************** //为pAdapterInfo分配空间 pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO)); ulOutBufLen = sizeof(IP_ADAPTER_INFO); //第一次调用GetAdaptersInfo(),获取返回结果的大小保存到ulOutBufLen中 if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS) { free(pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen); //pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen); } cout << pAdapterInfo->AddressLength; //第二次调用GetAdaptersInfo(),获取本地网络信息保存到结构体pAdapterInfo中 //dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); if ((dwRetVal=GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) != ERROR_SUCCESS) { cout << "GetAdaptersInfo Error!"<< dwRetVal << endl; } //***********************显示本地网络适配器信息****************** pAdapter = pAdapterInfo; while (pAdapter) { cout << "网络适配器名:" << pAdapter->AdapterName<<endl; cout << "网络适配器描述:" << pAdapter->Description << endl; cout << "MAC地址: " ; //处理MAC地址 for (int i = 0; i < pAdapter->AddressLength; i++) { if (i == (pAdapter->AddressLength - 1)) printf("%.2X ", (int)pAdapter->Address[i]); else printf("%.2X-", (int)pAdapter->Address[i]); } cout << "IP地址: " << pAdapter->IpAddressList.IpAddress.String<<endl; cout << "子网掩码: " << pAdapter->IpAddressList.IpMask.String<<endl; cout << "网关: " << pAdapter->GatewayList.IpAddress.String<<endl; if (pAdapter->DhcpEnabled) { cout << "启用DHCP:是"<<endl; cout << "DHCP服务器:" << pAdapter->DhcpServer.IpAddress.String; } else { cout << "启用DHCP:否" << endl; } cout << endl; //处理下一个网络适配器 pAdapter = pAdapter->Next; } //***************************释放资源******************** if (pAdapterInfo) free(pAdapterInfo); //*************************暂停程序,等待用户响应*************** printf(" "); //system("pause"); } //*********************二、获取本地主机名、域名、DNS服务器信息**************** void Network() { //********************2.声明变量**************************** //定义保存本地计算机网络参数信息的结构体指针 FIXED_INFO * FixedInfo; //保存获取到的本地计算机网络参数信息结构体链表的长度 ULONG ulOutBufLen; //调用GetNetworkParams()返回值 DWORD dwRetVal; //保存所有DNS服务器的IP地址列表 IP_ADDR_STRING* pIPAddr; //******************3.获取本地网络参数信息*************************** //为FixedInfo结构体分配内存空间 FixedInfo = (FIXED_INFO*)GlobalAlloc(GPTR, sizeof(FIXED_INFO)); //初始化ulOutBuflen变量值 ulOutBufLen = sizeof(FIXED_INFO); //第一次调用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){ cout << "调用GetNetworkParams()函数失败!返回值:" << dwRetVal << endl; } else { cout << "主机名:" << FixedInfo->HostName << endl; cout << "域名:" << FixedInfo->DomainName << endl; cout << "网络信息:" << endl; 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 = "Unknow Node"; break; } cout << "节点类型:" << FixedInfo->NodeType << NodeType << endl; printf("是否启用路由功能:%s ", (FixedInfo->EnableRouting != 0) ? "是" : "否"); printf("是否启用ARP代理功能:%s ", (FixedInfo->EnableProxy != 0) ? "是" : "否"); printf("是否启用DNS服务器:%s ", (FixedInfo->EnableDns != 0) ? "是" : "否"); printf(" 服务器列表 "); printf("%s ", FixedInfo->DnsServerList.IpAddress.String); pIPAddr = FixedInfo->DnsServerList.Next; while (pIPAddr){ printf(" %s ", pIPAddr->IpAddress.String); pIPAddr = pIPAddr->Next; } } printf(" "); } //*********************获取本地计算机网络接口的基本信息************************ void NumberOfInterfaces() { //保存网络接口信息的结构体指针 PIP_INTERFACE_INFO pInfo=NULL; //保存获取数据的长度 ULONG ulOutBufLen = 0; //返回结果 DWORD dwRetVal=0; int iReturn = 0; //第一次调用GetInterfaceInfo,获取数据大小,保存到ulOutBufLen变量中 dwRetVal = GetInterfaceInfo(NULL, &ulOutBufLen); if (dwRetVal == ERROR_INSUFFICIENT_BUFFER){ pInfo = (IP_INTERFACE_INFO *)malloc(ulOutBufLen); if (pInfo == NULL){ printf("无法分配GetInterfaceInfo函数需要的内存空间。 "); } } //第二次调用GetInterfaceInfo,获取需要的实际数据 dwRetVal = GetInterfaceInfo(pInfo, &ulOutBufLen); if (dwRetVal == NO_ERROR){ printf("网络适配器数量:%ld ", pInfo->NumAdapters); for (int i = 0; i < (int)pInfo->NumAdapters; i++) { printf("网络适配器索引[%d]:%ld ", i,pInfo->Adapter[i].Index); printf("网络适配器名称[%d]:%ws ", i, pInfo->Adapter[i].Name);//? } iReturn = 0; } else if (dwRetVal == ERROR_NO_DATA) { printf("本地计算机上没有支持IPV4的网络适配器。 "); iReturn = 1; } else{ printf("GetInterfaceInfo调用失败:%d ", dwRetVal); } //释放内存空间 free(pInfo); } //*****************获取本地计算机IP地址表********************** //分配内存空间 #define MALLOC(x) HeapAlloc(GetProcessHeap(),0,(x)) //释放内存空间 #define FREE(x) HeapFree(GetProcessHeap(),0,(x)) int GetIpAddr() { //网络接口与IP地址映射表 PMIB_IPADDRTABLE pIPAddrTable; //获取数据的大小 DWORD dwSize = 0; //调用GetIPAddrTable()函数的返回值 DWORD dwRetval = 0; //保存IP地址的结构体 IN_ADDR IPAddr; //用于获取错误信息 LPVOID lpMsgBuf; //IN_ADDR的定义如下: typedef struct in_addr IN_ADDR; //分配内存空间 pIPAddrTable = (MIB_IPADDRTABLE *)MALLOC(sizeof(MIB_IPADDRTABLE)); //第一次调用GetIPAddrTable()函数,获取数据的大小到dwSize if (pIPAddrTable) { if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER){ FREE(pIPAddrTable); pIPAddrTable = (MIB_IPADDRTABLE *)MALLOC(dwSize); } if (pIPAddrTable == NULL) { printf("GetIpAddrTable()函数内存分配失败 "); exit(1); } } //第2次调用GetIPAddrTable()函数,获取实际数据 if ((dwRetval = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR){ printf("GetIpAddrTable()调用失败:%d ", 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(" 错误信息:%s", lpMsgBuf); LocalFree(lpMsgBuf); } exit(1); } //显示获取到的IP地址信息 printf(" 记录数量:%ld ", pIPAddrTable->dwNumEntries); for (int i = 0; i < (int)pIPAddrTable->dwNumEntries; i++) { printf(" 接口序号[%d]: %ld ", i, pIPAddrTable->table[i].dwIndex); IPAddr.S_un.S_addr = (u_long)pIPAddrTable->table[i].dwAddr; printf(" IP地址[%d]: %s ", i, inet_ntoa(IPAddr)); IPAddr.S_un.S_addr = (u_long)pIPAddrTable->table[i].dwMask; printf(" 子网掩码[%d]: %s ", i, inet_ntoa(IPAddr)); IPAddr.S_un.S_addr = (u_long)pIPAddrTable->table[i].dwBCastAddr; printf(" 广播地址[%d]: %s(%ld%) ", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr); printf(" 重组报文最大数量[%d]: %ld ", i, pIPAddrTable->table[i].dwReasmSize); printf(" 类型和状态:[%d]:", i); if (pIPAddrTable->table[i].wType & MIB_IPADDR_PRIMARY) printf(" 主IP地址"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_DYNAMIC) printf(" 动态IP地址"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_DISCONNECTED) printf(" 断开连接的接口对应的IP地址"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_DELETED) printf(" 删除的IP地址"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_TRANSIENT) printf(" 临时地址"); printf(" "); } //释放内存空间 if (pIPAddrTable){ FREE(pIPAddrTable); pIPAddrTable = NULL; } return 0; }
GetNetworkParams.cpp
//********************1.声明头文件**************************** #include<iostream> #include<string> //#include"stdafx.h" #include"GetInfo.h" #include<WinSock2.h> #include<IPHlpApi.h> #include<stdio.h> #pragma comment(lib,"IPHLPAPI.lib") using namespace std; int main() { while (true) { cout << "请选择您要进行的操作:" << endl; cout << "1.获取本地网络适配器信息" << endl; cout << "2.获取本地主机名、域名、DNS服务器信息" << endl; cout << "3.获取本地计算机网络接口的基本信息" << endl; cout << "4.获取本地计算机IP地址表" << endl; cout << "其他键退出" << endl; string select = ""; cin >> select; if (select == "1") { pAdapter();//获取本地网络适配器信息 } else if (select == "2") { Network();//获取本地主机名、域名、DNS服务器信息 } else if (select == "3") { NumberOfInterfaces();//获取本地计算机网络接口的基本信息 } else if (select == "4") GetIpAddr();//获取本地计算机IP地址表 else { cout << "已退出" << endl; break; } } return 0; }