自动计算当前局域网IP段
多线程扫描
输出每个存活主机的IP和MAC地址,以及存活的总数(不带网卡厂商信息)
缺点:
自动获取区域网IP段 不可控IP 比如我扩大子网范围
遇到双网卡的情况下默认只扫描一个
/
//自动扫描局域网存活主机
//优点:不用输入ip
//缺点:如果遇到主机多IP只能扫描其中一个
#include <windows.h>
#include <stdio.h>
#include <iphlpapi.h>
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"iphlpapi.lib")
// 线程参数结构体
struct CThreadParam
{
UINT uIp; // 整数的ip地址
HANDLE hEventCopy; // 赋值参数的事件
};
CRITICAL_SECTION cs; // 打印时用到的临界区
UINT uTotal = 0; // 输出一共存活的主机
/// 用户扫描单个主机的线程函数
DWORD WINAPI LanScan(LPVOID param)
{
HRESULT result;
CThreadParam cParam;
ULONG c[2] = {0},len=6;
cParam = *(CThreadParam *)param;
SetEvent(cParam.hEventCopy);
// 这句关键
result = SendARP(htonl(cParam.uIp),NULL,c,&len); //发送ARP包
// 没有错误就输出
if(result == NO_ERROR)
{
UINT i;
BYTE *g = (BYTE *)&c;
in_addr target_addr;
target_addr.S_un.S_addr=htonl((cParam.uIp));
if (len)
{
::EnterCriticalSection(&cs);
printf("host %s living, max address:", inet_ntoa(target_addr));
for (i = 0; i < (int) len; i++)
{
if (i == (len - 1))
{
printf("%.2X\n", (int) g[i]);
}
else
{
printf("%.2X-", (int) g[i]);
}
}
uTotal++;
::LeaveCriticalSection(&cs);
}
}
return 0;
}
int main()
{
// 初始化socket
WSADATA data;
WORD wVersion = MAKEWORD(2,2);
WSAStartup(wVersion,&data);
hostent *pLocalHost;
HANDLE hEvent;
// 获得本机IP结构
pLocalHost = ::gethostbyname("");
// 这样获得是网络字节序
ULONG ulIpAddress = (*(struct in_addr *)*(pLocalHost->h_addr_list)).S_un.S_addr;
PIP_ADAPTER_INFO pAdapterInfo=NULL;
ULONG ulLen=0;
// 为适配器结构申请内存
::GetAdaptersInfo(pAdapterInfo,&ulLen);
pAdapterInfo=(PIP_ADAPTER_INFO)::GlobalAlloc(GPTR,ulLen);
// 初始化线程里用到的参数
::InitializeCriticalSection(&cs);
hEvent = ::CreateEventW(NULL, FALSE, FALSE, NULL);
CThreadParam cParam;
//取得本地适配器结构信息
if(::GetAdaptersInfo(pAdapterInfo,&ulLen)==ERROR_SUCCESS)
{
while (pAdapterInfo!=NULL)
{
if (::inet_addr(pAdapterInfo->IpAddressList.IpAddress.String) == ulIpAddress)
{
// 这里要转换为主机字节序
ULONG ulIpMask = ntohl(::inet_addr(pAdapterInfo->IpAddressList.IpMask.String));
// 与获得网络号
ULONG ulNetName = ntohl(ulIpAddress) & ulIpMask;
// 取非减2获得这个网段的主机数
UINT unNum = ~ulIpMask;
UINT nNumofHost = unNum - 2;
// 循环把主机的IP带入线程进行扫描
UINT i;
HANDLE hThread;
DWORD wThread;
for (i = 0; i < nNumofHost; i++)
{
// 存的都是主机字节序
cParam.uIp = ulNetName + i + 1;
cParam.hEventCopy = hEvent;
hThread = CreateThread(NULL, 0, LanScan, (LPVOID)&cParam, 0, &wThread);
::WaitForSingleObject(hEvent, INFINITE);
}
break;
}
pAdapterInfo = pAdapterInfo->Next;
}
}
// 休息5秒,等待线程执行结束
Sleep(5000);
printf("\ntotal = %d\n", uTotal);
return 0;
}
VS2008下编译的,如果用vc6.0要加SDK才有相关的头文件。
转载于:https://blog.51cto.com/0x007/1619183