/ //自动扫描局域网存活主机 本程序是利用arp协议去获取局域网中的存活主机
arp协议概述
地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机,并接收返回消息,以此确定目标的物理地址
定义数据结构
这个数据结构位ip和mac对应
typedef struct s_ip_fname
{
std:: vector< std:: string> ips;
std:: string mac;
} s_ip_fname;
下面的数据结构是为了存储mac地址的
typedef struct list_nim
{
atomic< uint32_t > v_n = 0 ;
std:: map< std:: string, std:: string> nim;
std:: mutex mutex;
void clear ( )
{
nim. clear ( ) ;
}
void push ( string & ip, string & mac)
{
mutex. lock ( ) ;
nim[ mac] = ip;
mutex. unlock ( ) ;
}
} list_nim;
获取IP地址
获取到本机的IP地址,本例子是可以获取网卡的多个IP地址
std:: string main_ip ( )
{
std:: vector< s_ip_fname> ip_mac_vector;
get_ipfname ( ip_mac_vector) ;
std:: string ip;
if ( ip_mac_vector. size ( ) == 0 )
return ip;
auto it = ip_mac_vector. begin ( ) ;
if ( it-> ips. size ( ) > 0 )
ip = it-> ips[ 0 ] ;
return ip;
}
其中获取get_ipfname 获取ip地址列表,写成了一个静态函数,我们无论如何都要想到,一个主机不一定只有一个网卡,一个网卡不一定只有一个ip
static int get_ipfname ( std:: vector< s_ip_fname> & ff)
{
# define ADDR ( x) pIpAdapterInfo-> Address[ x]
PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO ( ) ;
unsigned long stSize = sizeof ( IP_ADAPTER_INFO) ;
int nRel = GetAdaptersInfo ( pIpAdapterInfo, & stSize) ;
DWORD netCardNum = 0 ;
GetNumberOfInterfaces ( & netCardNum) ;
int IPnumPerNetCard = 0 ;
if ( ERROR_BUFFER_OVERFLOW == nRel)
{
delete pIpAdapterInfo;
pIpAdapterInfo = ( PIP_ADAPTER_INFO) new BYTE[ stSize] ;
nRel = GetAdaptersInfo ( pIpAdapterInfo, & stSize) ;
}
if ( ERROR_SUCCESS == nRel)
{
while ( pIpAdapterInfo)
{
s_ip_fname ipf;
switch ( pIpAdapterInfo-> Type)
{
case MIB_IF_TYPE_OTHER:
break ;
case MIB_IF_TYPE_ETHERNET:
break ;
case MIB_IF_TYPE_TOKENRING:
break ;
case MIB_IF_TYPE_FDDI:
break ;
case MIB_IF_TYPE_PPP:
break ;
case MIB_IF_TYPE_LOOPBACK:
break ;
case MIB_IF_TYPE_SLIP:
break ;
default :
break ;
}
char buffer[ 128 ] ;
sprintf ( buffer, "%02X-%02X-%02X-%02X-%02X-%02X" ,
ADDR ( 0 ) , ADDR ( 1 ) , ADDR ( 2 ) , ADDR ( 3 ) , ADDR ( 4 ) , ADDR ( 5 ) ) ;
ipf. mac = buffer;
IPnumPerNetCard = 0 ;
IP_ADDR_STRING* pIpAddrString = & ( pIpAdapterInfo-> IpAddressList) ;
do
{
ipf. ips. push_back ( pIpAddrString-> IpAddress. String) ;
pIpAddrString = pIpAddrString-> Next;
} while ( pIpAddrString) ;
ff. push_back ( ipf) ;
pIpAdapterInfo = pIpAdapterInfo-> Next;
}
}
if ( pIpAdapterInfo)
{
delete pIpAdapterInfo;
}
return 0 ;
}
线程函数
改函数启动一个线程,去发送arp请求
void start_thread ( int tn, uint32_t ulNetName)
{
thread th[ 256 ] ;
for ( int i = 0 ; i < tn; i++ )
{
th[ i] = thread ( [ this, ulNetName] {
while ( 1 )
{
uint32_t x = v_number-- ;
uint32_t n = htonl ( ulNetName + x + 1 ) ;
this-> send_arp ( n) ;
if ( v_number < 0 )
break ;
}
} ) ;
}
for ( int i = 0 ; i < tn; i++ )
th[ i] . join ( ) ;
}
send arp 函数实际上就是调用windows的辅助函数SendARP
void send_arp ( uint32_t naddr_f)
{
struct in_addr in;
in. S_un. S_addr = naddr_f;
string ip = inet_ntoa ( in) ;
std:: cout << "scan:" ;
std:: cout << ip. c_str ( ) << endl;
HRESULT result;
ULONG c[ 2 ] = { 0 } , len = 6 ;
result = SendARP ( naddr_f, NULL , c, & len) ;
if ( result == NO_ERROR)
{
BYTE * g = ( BYTE * ) & c;
if ( len)
{
string strmac ( 32 , 0 ) ;
sprintf ( const_cast< char * > ( strmac. c_str ( ) ) ,
"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X" ,
g[ 0 ] , g[ 1 ] , g[ 2 ] , g[ 3 ] , g[ 4 ] , g[ 5 ] ) ;
v_lnim. push ( strmac, ip) ;
}
}
}
目标
//自动扫描局域网存活主机 程序清单,复制可用 / //自动扫描局域网存活主机 //优点:不用输入ip //缺点:如果遇到主机多IP只能扫描其中一个
# include <winsock2.h>
# include <stdio.h>
# include <iphlpapi.h>
# pragma comment ( lib, "ws2_32.lib" )
# pragma comment ( lib, "iphlpapi.lib" )
# include <iostream>
# include <list>
# include <windows.h>
# include <thread>
# include <atomic>
# include <mutex>
# include <map>
# include <vector>
using namespace std;
typedef struct s_ip_fname
{
std:: vector< std:: string> ips;
std:: string mac;
} s_ip_fname;
typedef struct list_nim
{
atomic< uint32_t > v_n = 0 ;
std:: map< std:: string, std:: string> nim;
std:: mutex mutex;
void clear ( )
{
nim. clear ( ) ;
}
void push ( string & ip, string & mac)
{
mutex. lock ( ) ;
nim[ mac] = ip;
mutex. unlock ( ) ;
}
} list_nim;
static int get_ipfname ( std:: vector< s_ip_fname> & ff)
{
# define ADDR ( x) pIpAdapterInfo-> Address[ x]
PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO ( ) ;
unsigned long stSize = sizeof ( IP_ADAPTER_INFO) ;
int nRel = GetAdaptersInfo ( pIpAdapterInfo, & stSize) ;
DWORD netCardNum = 0 ;
GetNumberOfInterfaces ( & netCardNum) ;
int IPnumPerNetCard = 0 ;
if ( ERROR_BUFFER_OVERFLOW == nRel)
{
delete pIpAdapterInfo;
pIpAdapterInfo = ( PIP_ADAPTER_INFO) new BYTE[ stSize] ;
nRel = GetAdaptersInfo ( pIpAdapterInfo, & stSize) ;
}
if ( ERROR_SUCCESS == nRel)
{
while ( pIpAdapterInfo)
{
s_ip_fname ipf;
switch ( pIpAdapterInfo-> Type)
{
case MIB_IF_TYPE_OTHER:
break ;
case MIB_IF_TYPE_ETHERNET:
break ;
case MIB_IF_TYPE_TOKENRING:
break ;
case MIB_IF_TYPE_FDDI:
break ;
case MIB_IF_TYPE_PPP:
break ;
case MIB_IF_TYPE_LOOPBACK:
break ;
case MIB_IF_TYPE_SLIP:
break ;
default :
break ;
}
char buffer[ 128 ] ;
sprintf ( buffer, "%02X-%02X-%02X-%02X-%02X-%02X" ,
ADDR ( 0 ) , ADDR ( 1 ) , ADDR ( 2 ) , ADDR ( 3 ) , ADDR ( 4 ) , ADDR ( 5 ) ) ;
ipf. mac = buffer;
IPnumPerNetCard = 0 ;
IP_ADDR_STRING* pIpAddrString = & ( pIpAdapterInfo-> IpAddressList) ;
do
{
ipf. ips. push_back ( pIpAddrString-> IpAddress. String) ;
pIpAddrString = pIpAddrString-> Next;
} while ( pIpAddrString) ;
ff. push_back ( ipf) ;
pIpAdapterInfo = pIpAdapterInfo-> Next;
}
}
if ( pIpAdapterInfo)
{
delete pIpAdapterInfo;
}
return 0 ;
}
class c_arp
{
list_nim v_lnim;
std:: atomic< int > v_number = 0 ;
public:
~ c_arp ( )
{
v_lnim. clear ( ) ;
}
size_t size ( )
{
return v_lnim. nim. size ( ) ;
}
void set_max_ip ( uint32_t number)
{
v_number = number;
}
void send_arp ( uint32_t naddr_f)
{
struct in_addr in;
in. S_un. S_addr = naddr_f;
string ip = inet_ntoa ( in) ;
std:: cout << "scan:" ;
std:: cout << ip. c_str ( ) << endl;
HRESULT result;
ULONG c[ 2 ] = { 0 } , len = 6 ;
result = SendARP ( naddr_f, NULL , c, & len) ;
if ( result == NO_ERROR)
{
BYTE * g = ( BYTE * ) & c;
if ( len)
{
string strmac ( 32 , 0 ) ;
sprintf ( const_cast< char * > ( strmac. c_str ( ) ) ,
"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X" ,
g[ 0 ] , g[ 1 ] , g[ 2 ] , g[ 3 ] , g[ 4 ] , g[ 5 ] ) ;
v_lnim. push ( strmac, ip) ;
}
}
}
void start_thread ( int tn, uint32_t ulNetName)
{
thread th[ 256 ] ;
for ( int i = 0 ; i < tn; i++ )
{
th[ i] = thread ( [ this, ulNetName] {
while ( 1 )
{
uint32_t x = v_number-- ;
uint32_t n = htonl ( ulNetName + x + 1 ) ;
this-> send_arp ( n) ;
if ( v_number < 0 )
break ;
}
} ) ;
}
for ( int i = 0 ; i < tn; i++ )
th[ i] . join ( ) ;
}
void print ( )
{
for ( auto iter : v_lnim. nim)
{
std:: cout << iter. first. c_str ( ) << ":" << iter. second. c_str ( ) << endl;
}
}
} ;
std:: string main_ip ( )
{
std:: vector< s_ip_fname> ip_mac_vector;
get_ipfname ( ip_mac_vector) ;
std:: string ip;
if ( ip_mac_vector. size ( ) == 0 )
return ip;
auto it = ip_mac_vector. begin ( ) ;
if ( it-> ips. size ( ) > 0 )
ip = it-> ips[ 0 ] ;
return ip;
}
int main ( )
{
WSADATA data;
WORD wVersion = MAKEWORD ( 2 , 2 ) ;
WSAStartup ( wVersion, & data) ;
hostent * pLocalHost;
pLocalHost = :: gethostbyname ( "" ) ;
std:: string ip = main_ip ( ) ;
ULONG ulIpAddress = inet_addr ( ip. c_str ( ) ) ;
PIP_ADAPTER_INFO pAdapterInfo = NULL ;
ULONG ulLen = 0 ;
:: GetAdaptersInfo ( pAdapterInfo, & ulLen) ;
pAdapterInfo = ( PIP_ADAPTER_INFO) :: GlobalAlloc ( GPTR, ulLen) ;
c_arp arp;
if ( :: GetAdaptersInfo ( pAdapterInfo, & ulLen) == ERROR_SUCCESS)
{
while ( pAdapterInfo != NULL )
{
if ( ip. compare ( pAdapterInfo-> IpAddressList. IpAddress. String) == 0 )
{
ULONG ulIpMask = ntohl ( :: inet_addr ( pAdapterInfo-> IpAddressList. IpMask. String) ) ;
ULONG ulNetName = ntohl ( ulIpAddress) & ulIpMask;
UINT unNum = ~ ulIpMask;
UINT nNumofHost = unNum - 2 ;
arp. set_max_ip ( nNumofHost) ;