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地址: \t" ;
//处理MAC地址
for (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]);
}
cout << "IP地址:\t" << pAdapter->IpAddressList.IpAddress.String<<endl;
cout << "子网掩码:\t" << pAdapter->IpAddressList.IpMask.String<<endl;
cout << "网关:\t" << 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("\n\n");
//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\n", (FixedInfo->EnableRouting != 0) ? "是" : "否");
printf("是否启用ARP代理功能:%s\n", (FixedInfo->EnableProxy != 0) ? "是" : "否");
printf("是否启用DNS服务器:%s\n", (FixedInfo->EnableDns != 0) ? "是" : "否");
printf("\n服务器列表\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");
}
//*********************获取本地计算机网络接口的基本信息************************
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函数需要的内存空间。\n");
}
}
//第二次调用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 = 1;
}
else{
printf("GetInterfaceInfo调用失败:%d\n", 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()函数内存分配失败\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);
}
//显示获取到的IP地址信息
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;
}
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;
}