第一个参数为要获取其MAC地址的目标计算机机的IP地址,参数类型为IPAddr ,其实类型就是unsigned long (用户输入的目的主机的IP地址一般是字符串类型点式IP地址,需要将其转换成一个3 2位的无符号长整数,可用inet_addr函数完成);第二个参数为源机的IP地址;第三个参数为存放目标计算机MAC地址的指针变量;第四个参数为存放目标计算机MAC地址字节长度的指针变量。该函数的定义在iphlpapi.h头文件中,所以要包含#include<iphlpapi.h>;该函数的实现在Iphlpapi.lib库文件中,要在项目设置的链接中加入库文件Iphlpapi.lib。(注意:VC6.0不含这两个文件,需网上下载,而VC7.0中含有。)关键代码如下:
//将用户输入的目的主机的字符串类型点式IP地址转换成一个3 2位的无符号长整数:
ULONG ULDestIP=inet_addr(strIPAddr);
//发送ARP请求包获得远程MAC地址:
iRusult=SendARP(ULDestIP,(unsigned long)NULL,(PULONG)&ULMacAdd,&PhyAddrLen);
//由于获得的MAC地址是6字节的unsigned char数值,不便阅读,所以需要将其转换为字符串:
sprintf(strMacAddr,"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",ULMacAdd[0],ULMacAdd[1],ULMacAdd[2],ULMacAdd[3],ULMacAdd[4],ULMacAdd[5]);
为了实现获取机房内所有机器的MAC地址,可以采取循环的办法发送ARP请求包获得所有机器的MAC地址,考虑机房内机器的IP地址一般都是连续的,所以先获取IP地址最小的那台机器的MAC地址,然后逐一增加IP地址, 循环获取其它机器的IP地址。
//注意IP地址加一前先要将ULONG类型的IP地址从网络字节顺序转换为主机字节顺序,加一后再从主机字节顺序转换为网络字节顺序。
ULDestIP=htonl(ntohl(ULDestIP)+1);
为了使用户能对比观察及关机的需要,程序中还获取了远程机的机器名,并与IP地址、MAC地址一起显示在一个ListCtrl控件中。
//获取远程机器名:
struct hostent *RemoteHost;
RemoteHost=(struct hostent*)malloc(sizeof(struct hostent));
RemoteHost=gethostbyaddr((char*)&ULDestIP,4,AF_INET);
strcpy(strRemoteHostName,RemoteHost->h_name);
//将3 2位的无符号长整数IP地址转换成字符串类型点式IP地址:
struct in_addr sAddr;
sAddr.s_addr=ULDestIP;
strcpy(strIPAddr,inet_ntoa(sAddr));
//将远程机的机器名、IP地址、MAC地址一起显示在一个ListCtrl控件中:
int iItemNumber=m_ListHostInfo.GetItemCount();
char strNumber[4];
sprintf(strNumber,"%d",iItemNumber+1);
m_ListHostInfo.InsertItem(iItemNumber,strNumber); //第一列显示序号
m_ListHostInfo.SetItemText(iItemNumber,1,strRemoteHostName); //第二列显示机器名
m_ListHostInfo.SetItemText(iItemNumber,2,strIPAddr); //第三列显示IP地址
m_ListHostInfo.SetItemText(iItemNumber,3,strMacAddr); //第四列显示MAC地址
为了下次开机的需要,要将ListCtrl控件中显示的机器名、IP地址、MAC地址一一对应保存在一个文件中。远程开机前,需要将文件中的机器名、IP地址、MAC地址读出来显示在ListCtrl控件中,在程序启动后(比如在OnInitDialog函数中)就读出来显示,以便开机和关机都可以使用。文件读写的代码比较简单,这里就不再赘述。
|