我们在进行网络编程的时候,经常需要获取本地主机,网卡的信息,我们代码实现如下。
#include "../common/initsock.h"
#include <windows.h>
#include <stdio.h>
#include <Iphlpapi.h>
#include "protoutils.h"
#include "ProtoPacket.h"
#pragma comment(lib, "Iphlpapi.lib")
DWORD WINAPI SendThread(LPVOID lpParam);
BOOL GetGlobalData();
/
// 全局数据
u_char g_ucLocalMac[6]; // 本地MAC地址
DWORD g_dwGatewayIP; // 网关IP地址
DWORD g_dwLocalIP; // 本地IP地址
DWORD g_dwMask; // 子网掩码
CInitSock theSock;
int main()
{
// 获取全局数据
GetGlobalData();
// 启动服务
if(!ProtoStartService())
{
printf(" ProtoStartService() failed %d \n", ::GetLastError());
return -1;
}
// 打开控制设备对象
HANDLE hControlDevice = ProtoOpenControlDevice();
if(hControlDevice == INVALID_HANDLE_VALUE)
{
printf(" ProtoOpenControlDevice() failed() %d \n", ::GetLastError());
ProtoStopService();
return -1;
}
// 枚举绑定的下层适配器
CPROTOAdapters adapters;
if(!adapters.EnumAdapters(hControlDevice))
{
printf(" Enume adapter failed \n");
ProtoStopService();
return -1;
}
CAdapter adapter;
// 默认使用第一个适配器
if(!adapter.OpenAdapter(adapters.m_pwszSymbolicLink[0], TRUE))
{
printf(" OpenAdapter failed \n");
ProtoStopService();
return -1;
}
CArpPacket arp(&adapter);
// 下面开始进行LAN扫描
// 提供当前线程(接收数据的线程)的优先级,避免丢失到来的数据贞
::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
// 创建发送线程,开始发送ARP请求
::CloseHandle(::CreateThread(NULL, 0, SendThread, &arp, 0, NULL));
// 接收ARP应答
u_char *p;
PARPHeader pArph;
printf(" 开始扫描LAN中的计算机... \n");
while(TRUE)
{
pArph = arp.WaitReply();
if(pArph != NULL)
{
printf(" \n ------------------------------------------- \n");
p = pArph->smac;
printf(" Mac地址: %02X-%02X-%02X-%02X-%02X-%02X \n", p[0], p[1], p[2], p[3], p[4], p[5]);
p = (u_char*)&pArph->saddr;
printf(" IP地址: %d.%d.%d.%d \n ", p[0], p[1], p[2], p[3]);
// HOSTENT *pHost = ::gethostbyaddr((char*)&pArph->saddr, 4, AF_INET);
// if(pHost != NULL)
// printf(" 主机名: %s \n", pHost->h_name);
}
else
{
break;
}
}
printf("\n\n 扫描完毕 \n");
ProtoStopService();
getchar();
return 0;
}
DWORD WINAPI SendThread(LPVOID lpParam)
{
CArpPacket *pArp = (CArpPacket *)lpParam;
// 取得LAN中IP地址空间的大小
DWORD dwMask = ::ntohl(g_dwMask);
int nMaxHosts = ~dwMask;
// 设置以太头中目标MAC地址。发送ARP请求时,应该将它设为广播地址
u_char destmacEther[6];
memset(destmacEther, 0xff, 6);
// ARP头中的目标MAC地址
u_char destmacArp[6] = { 0 };
// 向地址空间中的每个IP地址发送ARP请求
DWORD dwTemp = ::ntohl(g_dwGatewayIP & g_dwMask) + 1;
for(int i=1; i<nMaxHosts; i++, dwTemp++)
{
DWORD dwIP = ::htonl(dwTemp);
if(dwIP != g_dwLocalIP)
{
if(!pArp->SendPacket(destmacEther, g_ucLocalMac, ARPOP_REQUEST,
destmacArp, dwIP, g_ucLocalMac, g_dwLocalIP))
{
printf(" SendPacket() failed \n");
break;
}
}
}
return 0;
}
BOOL GetGlobalData()
{
PIP_ADAPTER_INFO pAdapterInfo = NULL;
ULONG ulLen = 0;
// 为适配器结构申请内存
::GetAdaptersInfo(pAdapterInfo,&ulLen);
pAdapterInfo = (PIP_ADAPTER_INFO)::GlobalAlloc(GPTR, ulLen);
// 取得本地适配器结构信息
if(::GetAdaptersInfo(pAdapterInfo,&ulLen) == ERROR_SUCCESS)
{
if(pAdapterInfo != NULL)
{
memcpy(g_ucLocalMac, pAdapterInfo->Address, 6);
g_dwGatewayIP = ::inet_addr(pAdapterInfo->GatewayList.IpAddress.String);
g_dwLocalIP = ::inet_addr(pAdapterInfo->IpAddressList.IpAddress.String);
g_dwMask = ::inet_addr(pAdapterInfo->IpAddressList.IpMask.String);
}
}
::GlobalFree(pAdapterInfo);
printf(" \n -------------------- 本地主机信息 -----------------------\n\n");
in_addr in;
in.S_un.S_addr = g_dwLocalIP;
printf(" IP Address : %s \n", ::inet_ntoa(in));
in.S_un.S_addr = g_dwMask;
printf(" Subnet Mask : %s \n", ::inet_ntoa(in));
in.S_un.S_addr = g_dwGatewayIP;
printf(" Default Gateway : %s \n", ::inet_ntoa(in));
u_char *p = g_ucLocalMac;
printf(" MAC Address : %02X-%02X-%02X-%02X-%02X-%02X \n", p[0], p[1], p[2], p[3], p[4], p[5]);
printf(" \n \n ");
return TRUE;
}