扫描子网中的地址+Pings模拟

1. 计算子网内包含的所有的IP地址

// CalculateSubnet.cpp -- 计算指定子网内包含的所有的IP地址

#include "Winsock2.h"
#include <string>
#include <ctype.h>

#pragma comment(lib, "Ws2_32.lib")

/**
 * bool IsValidIP(char* ip) 
 * 功能:判断指定的IP地址是否有效。
 * 1. 字符串中必须包含3个符号"."
 * 2. 被符号"."分隔的字符串必须小于或等于3
 * 3. 被符号"."分隔的字符串必须可以转换成不大于255的整数。
 **/

bool IsValidIP(char* ip)
{
	std::string sip = ip;

	for (int judgeTimes = 1; judgeTimes <= 4; ++judgeTimes){
		int pos = (int)sip.find_first_of("."); // 找下一个句点
		if(0 == pos){
			return false;
		}
		std::string subip = sip.substr(0, pos);			// 将ip分割为左边有效的地方
		sip = sip.substr(pos+1, sip.length() - pos );	// 将ip分割为右边有效的地方

		if(subip.length() > 3){		// 长度必须不大于3
			return false;
		}
		for(int i=0; i< (int)subip.length(); i++){	// 检查是否满足全为数字的条件
			if(!isdigit(subip[i])){
				return false;
			}
		}
		int a = atoi(subip.c_str());	// 检查数字是否在取值范围内
		if(1 == judgeTimes && (a < 1 || a > 255)){
			return false;
		}
		else if((2 == judgeTimes || 3 == judgeTimes) && a > 255){
			return false;
		}
		else if(4 == judgeTimes && a > 254){
			return false;
		}
	}
	return true;
}



int main()
{
	const int argc = 3;
    char * argv[] = {"", "192.168.0.1", "255.255.255.0"};
	if(argc != 3){
		printf("Usage: CalculateSubnet netaddr netmask\r\nExample: CalculateSubnet 192.168.0.0 255.255.255.0\n");
		return 1;
	}
	if(!IsValidIP(argv[1]))	{
		printf("%s is not a valid ip.\n", argv[1]);
		return 1;
	}
	if(!IsValidIP(argv[2]))	{
		printf("%s is not a valid ip.\n", argv[2]);
		return 1;
	}
	printf("计算指定子网内包含的所有的IP地址\n");
	printf("netaddr: %s\n", argv[1]);
	printf("netmask: %s\n", argv[2]);
	unsigned long lnetaddr = ntohl(inet_addr(argv[1]));	// IP地址
	unsigned long lnetmask = ntohl(inet_addr(argv[2])); // 子网掩码
	unsigned long l_first_netaddr = lnetaddr & lnetmask;	// 子网地址=IP地址&子网掩码
	unsigned long l_broadcast = lnetaddr | ~lnetmask;       // 广播地址=IP地址|~子网掩码
	// 计算子网中包含有效IP地址的数量
	long num = l_broadcast - l_first_netaddr - 1;
	printf("Number of valid IPs: %d\n\n", num);

	printf("IPs in subnet: \n=============\n");
	for(unsigned long i = l_first_netaddr+1; i < l_broadcast; i++)	{
		in_addr IPAddr;
		IPAddr.S_un.S_addr = ntohl(i);
		printf("%s\n", inet_ntoa(IPAddr));
	}

	system("pause");
	return 0;
}

/** 运行结果:

计算指定子网内包含的所有的IP地址
netaddr: 192.168.0.1
netmask: 255.255.255.0
Number of valid IPs: 254

IPs in subnet:
=============
192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4
192.168.0.5
192.168.0.6
192.168.0.7
192.168.0.8
192.168.0.9
192.168.0.10
192.168.0.11
192.168.0.12
192.168.0.13
192.168.0.14
192.168.0.15
192.168.0.16
192.168.0.17
192.168.0.18
192.168.0.19
192.168.0.20
192.168.0.21
192.168.0.22
192.168.0.23
192.168.0.24
192.168.0.25
192.168.0.26
192.168.0.27
192.168.0.28
192.168.0.29
192.168.0.30
192.168.0.31
192.168.0.32
192.168.0.33
192.168.0.34
192.168.0.35
192.168.0.36
192.168.0.37
192.168.0.38
192.168.0.39
192.168.0.40
192.168.0.41
192.168.0.42
192.168.0.43
192.168.0.44
192.168.0.45
192.168.0.46
192.168.0.47
192.168.0.48
192.168.0.49
192.168.0.50
192.168.0.51
192.168.0.52
192.168.0.53
192.168.0.54
192.168.0.55
192.168.0.56
192.168.0.57
192.168.0.58
192.168.0.59
192.168.0.60
192.168.0.61
192.168.0.62
192.168.0.63
192.168.0.64
192.168.0.65
192.168.0.66
192.168.0.67
192.168.0.68
192.168.0.69
192.168.0.70
192.168.0.71
192.168.0.72
192.168.0.73
192.168.0.74
192.168.0.75
192.168.0.76
192.168.0.77
192.168.0.78
192.168.0.79
192.168.0.80
192.168.0.81
192.168.0.82
192.168.0.83
192.168.0.84
192.168.0.85
192.168.0.86
192.168.0.87
192.168.0.88
192.168.0.89
192.168.0.90
192.168.0.91
192.168.0.92
192.168.0.93
192.168.0.94
192.168.0.95
192.168.0.96
192.168.0.97
192.168.0.98
192.168.0.99
192.168.0.100
192.168.0.101
192.168.0.102
192.168.0.103
192.168.0.104
192.168.0.105
192.168.0.106
192.168.0.107
192.168.0.108
192.168.0.109
192.168.0.110
192.168.0.111
192.168.0.112
192.168.0.113
192.168.0.114
192.168.0.115
192.168.0.116
192.168.0.117
192.168.0.118
192.168.0.119
192.168.0.120
192.168.0.121
192.168.0.122
192.168.0.123
192.168.0.124
192.168.0.125
192.168.0.126
192.168.0.127
192.168.0.128
192.168.0.129
192.168.0.130
192.168.0.131
192.168.0.132
192.168.0.133
192.168.0.134
192.168.0.135
192.168.0.136
192.168.0.137
192.168.0.138
192.168.0.139
192.168.0.140
192.168.0.141
192.168.0.142
192.168.0.143
192.168.0.144
192.168.0.145
192.168.0.146
192.168.0.147
192.168.0.148
192.168.0.149
192.168.0.150
192.168.0.151
192.168.0.152
192.168.0.153
192.168.0.154
192.168.0.155
192.168.0.156
192.168.0.157
192.168.0.158
192.168.0.159
192.168.0.160
192.168.0.161
192.168.0.162
192.168.0.163
192.168.0.164
192.168.0.165
192.168.0.166
192.168.0.167
192.168.0.168
192.168.0.169
192.168.0.170
192.168.0.171
192.168.0.172
192.168.0.173
192.168.0.174
192.168.0.175
192.168.0.176
192.168.0.177
192.168.0.178
192.168.0.179
192.168.0.180
192.168.0.181
192.168.0.182
192.168.0.183
192.168.0.184
192.168.0.185
192.168.0.186
192.168.0.187
192.168.0.188
192.168.0.189
192.168.0.190
192.168.0.191
192.168.0.192
192.168.0.193
192.168.0.194
192.168.0.195
192.168.0.196
192.168.0.197
192.168.0.198
192.168.0.199
192.168.0.200
192.168.0.201
192.168.0.202
192.168.0.203
192.168.0.204
192.168.0.205
192.168.0.206
192.168.0.207
192.168.0.208
192.168.0.209
192.168.0.210
192.168.0.211
192.168.0.212
192.168.0.213
192.168.0.214
192.168.0.215
192.168.0.216
192.168.0.217
192.168.0.218
192.168.0.219
192.168.0.220
192.168.0.221
192.168.0.222
192.168.0.223
192.168.0.224
192.168.0.225
192.168.0.226
192.168.0.227
192.168.0.228
192.168.0.229
192.168.0.230
192.168.0.231
192.168.0.232
192.168.0.233
192.168.0.234
192.168.0.235
192.168.0.236
192.168.0.237
192.168.0.238
192.168.0.239
192.168.0.240
192.168.0.241
192.168.0.242
192.168.0.243
192.168.0.244
192.168.0.245
192.168.0.246
192.168.0.247
192.168.0.248
192.168.0.249
192.168.0.250
192.168.0.251
192.168.0.252
192.168.0.253
192.168.0.254
请按任意键继续. . .

**/


 

2. 实现ping功能扫描子网

// scanAllSubnetIPAddress.cpp -- 实现ping功能扫描子网

#include <string>
#include <map>
#include <list>
#include <winsock2.h>

#pragma comment(lib, "Ws2_32.lib")
using namespace std;

const int ICMP_MIN = 8;			// ICMP包的最小长度为8个字节,只包含包头
const int DEF_PACKET_SIZE = 32;	// 执行ping操作时指定发送数据包的缺省大小
const int MAX_PACKET = 1024;	// 执行ping操作时指定发送数据包的最大大小
const int ICMP_ECHO = 8;		// 表示ICMP包为回射请求包
const int ICMP_ECHOREPLY = 0;	// 表示ICMP包为回射应答包


// IP数据包头结构
typedef struct iphdr {
	unsigned int h_len:4;			// 包头长度
	unsigned int version:4;			// IP协议版本
	unsigned char tos;				// 服务类型(TOS)
	unsigned short total_len;		// 包的总长度
	unsigned short ident;			// 包的唯一标识
	unsigned short frag_and_flags;	// 标识
	unsigned char ttl;				// 生存时间(TTL)
	unsigned char proto;			// 传输协议 (TCP, UDP等)
	unsigned short checksum;		// IP校验和
	unsigned int sourceIP;
	unsigned int destIP;
}IpHeader;

// 执行ping操作时,定义发送IP数据包中包含的ICMP数据头结构
typedef struct _ihdr {
	BYTE i_type;			// 类型
	BYTE i_code;			// 编码
	USHORT i_cksum;			// 检验和
	USHORT i_id;			// 编号
	USHORT i_seq;			// 序列号
	ULONG timestamp;    	// 时间戳
}IcmpHeader;

// 用于描述要执行ping操作的结构体
struct PingPair{
	unsigned long ip;			// 执行ping操作的IP地址
	LARGE_INTEGER starttime;	// ping操作的开始时间
	LARGE_INTEGER endtime;		// ping操作的结束时间
	bool flag;					// 表示当前IP地址是否在线
	int period;					// ping操作的用时
	PingPair(): ip(0), flag(false), period(-1){}
	PingPair(int ipp): ip(ipp), flag(false), period(-1)	{}
};

// 用于发送ICMP包的线程结构
struct ThreadStruct{
	std::map<unsigned long, PingPair*> *ips;	// 要执行ping操作的IP地址映射表
	SOCKET s;									// 执行ping操作所使用的套接字
	int  timeout;								// ping超时时间
	DWORD  tid;									// 线程ID
	bool *sendCompleted;						// 标识是否完成批量ping操作
};


/**
 * 各函数解释
 * fill_icmp_data     填充ICMP请求包。
 * checksum           计算ICMP校验和。
 * decode_resp        对返回的IP数据包进行解码,定位到ICMP数据
 * SendIcmp           使用指定的Socket向指定的单个IP地址发送ICMP请求包
 * RecvIcmp           接收一个ICMP回应包
 * RecvThreadProc     批量接收ICMP回应包的线程函数
 * CreateSocket       创建Socket
 * DestroySocket      释放Socket
 * pings              启动多线程对一组地址执行ping操作
 * FillSubnet         计算指定子网中包含的所有IP地址列表。
 * ScanSubnet         扫描子网中所有的IP地址,返回在线的IP地址。
 **/


// 填充ICMP请求包
void fill_icmp_data(char * icmp_data, int datasize)
{
	IcmpHeader *icmp_hdr;
	char *datapart;	// 将缓冲区转换为icmp_hdr结构
	icmp_hdr = (IcmpHeader*)icmp_data;	// 填充各字段的值
	icmp_hdr->i_type = ICMP_ECHO;		// 将类型设置为ICMP响应包
	icmp_hdr->i_code = 0;				// 将编码设置为0
	icmp_hdr->i_id = (USHORT)GetCurrentThreadId();	// 将编号设置为当前线程的编号
	icmp_hdr->i_cksum = 0;				// 将校验和设置为0
	icmp_hdr->i_seq = 0;				// 将序列号设置为0
	datapart = icmp_data + sizeof(IcmpHeader);		// 定义到数据部分
	memset(datapart,'E', datasize - sizeof(IcmpHeader));// 在数据部分随便填充一些数据
	return;
}


// 创建套接字
SOCKET CreateSocket(DWORD timeout)
{
	WSADATA wsaData;
	SOCKET sockRaw = NULL;
	// 初始化
	if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0){
		return sockRaw;
	}
	// 创建原始套接字
	sockRaw = WSASocket (AF_INET, SOCK_RAW,	IPPROTO_ICMP, NULL, 0,WSA_FLAG_OVERLAPPED);
	if (sockRaw == INVALID_SOCKET) {
		return sockRaw;// WSASocket 错误
	}
	// 设置接收超时时间
	setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,	sizeof(timeout));
	// 设置发送超时时间
	setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,	sizeof(timeout));
	return sockRaw;
}

// 释放套接字
void DestroySocket(SOCKET sockRaw)
{
	closesocket(sockRaw);
	WSACleanup();
}

// 计算ICMP包的校验和
USHORT checksum(USHORT *buffer, int size)
{
	unsigned long cksum=0;
	// 把缓冲区中的数据相加
	while(size > 1) {
		cksum += *buffer++;
		size -= sizeof(USHORT);
	}
	if(size ) {
		cksum += *(UCHAR*)buffer;
	}
	cksum = (cksum >> 16) + (cksum & 0xffff);
	cksum += (cksum >> 16);
	return (USHORT)(~cksum);
}


// 使用指定的套接字向指定的单个IP地址发送ICMP请求包
// 参数sockRaw,指定发送ICMP请求包的套接字
// 参数ip,指定发送ICMP请求包的目标地址
bool SendIcmp(SOCKET sockRaw, unsigned long ip)
{
	struct sockaddr_in dest,from;				// 保存目标地址和源地址
	int datasize;								// 指定ICMP数据包的大小
	int fromlen = sizeof(from);					// 源地址长度
	unsigned long addr=0;						// 保存主机字节序IP地址
	USHORT seq_no = 0;							// 指定当前ICMP数据包的序号
	int ret = -1;								// 保存函数的返回值

	// 将ip转换为dest,以便执行ping操作
	memset(&dest,0,sizeof(dest));
	addr = ntohl(ip);
	dest.sin_addr.s_addr = addr;
	dest.sin_family = AF_INET;
	// 设置ICMP数据包的大小
	datasize = DEF_PACKET_SIZE;
	datasize += sizeof(IcmpHeader);
	// 填充ICMP数据包
	char icmp_data[MAX_PACKET];
	memset(icmp_data,0,MAX_PACKET);
	fill_icmp_data(icmp_data,datasize);


	// 设置ICMP包头中的校验和、时间戳和序号
	((IcmpHeader*)icmp_data)->i_cksum = 0;
	((IcmpHeader*)icmp_data)->timestamp = GetTickCount();
	((IcmpHeader*)icmp_data)->i_seq = seq_no++;
	((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data,
		datasize);
	// 向dest发送ICMP数据包
	int bwrote;
	bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,	sizeof(dest));
	// 发送失败,则返回false
	if (bwrote == SOCKET_ERROR){
		if (WSAGetLastError() != WSAETIMEDOUT)	{
			ret = false; // 发送错误
		}
	}
	if (bwrote < datasize ) {
		return false;
	}
	//发送成功,返回true
	return true;
}

// 对返回的IP数据包进行解码,定位到ICMP数据
// 因为ICMP数据包含在IP数据包中
int decode_resp(char *buf, int bytes, struct sockaddr_in *from, DWORD tid)
{
	IpHeader *iphdr;				// IP数据包头
	IcmpHeader *icmphdr;			// ICMP包头
	unsigned short iphdrlen;		// IP数据包头的长度
	iphdr = (IpHeader *)buf;		// 从buf中IP数据包头的指针
	// 计算IP数据包头的长度
	iphdrlen = iphdr->h_len * 4 ; // number of 32-bit words *4 = bytes
	// 如果指定的缓冲区长度小于IP包头加上最小的ICMP包长度,则说明它包含的ICMP数据不完整,或者不包含ICMP数据
	if (bytes < iphdrlen + ICMP_MIN) {
		return -1; //printf("Too few bytes from %s\n",inet_ntoa(from->sin_addr));
	}
	// 定位到ICMP包头的起始位置
	icmphdr = (IcmpHeader*)(buf + iphdrlen);
	// 如果ICMP包的类型不是回应包,则不处理
	if (icmphdr->i_type != ICMP_ECHOREPLY) {
		return -2; //fprintf(stderr,"non-echo type %d recvd\n",icmphdr->i_type);
	}
	// 发送的ICMP包ID和接收到的ICMP包ID应该对应
	if (icmphdr->i_id != (USHORT)tid){ //(USHORT)GetCurrentProcessId()) {
		return -3; //fprintf(stderr,"someone else's packet!\n");
	}
	// 返回发送ICMP包和接收回应包的时间差
	int time = GetTickCount() - (icmphdr->timestamp);
	if(time >= 0)
		return time;
	else
		return -4; // 时间值不对
}


// 接收一个ICMP回应包
// 参数sockRaw指定接收ICMP回应包的套接字
// 参数ip指定发送ICMP回应包的IP地址
// 参数tid指定发送ICMP回应包的线程ID
int RecvIcmp(SOCKET sockRaw, unsigned long *ip, DWORD tid)
{
	struct sockaddr_in from;			// 接收到ICMP的来自的地址
	int fromlen = sizeof(from);	    	// 地址from的长度
	int bread;							// 调用recvfrom()函数的返回结果
	char recvbuf[MAX_PACKET];			// 用于接收ICMP回应我的缓冲区
	// 接收ICMP回应包
	bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,	&fromlen);
	if (bread == SOCKET_ERROR){
		if (WSAGetLastError() == WSAETIMEDOUT) {
			return -1; // 超时
		}
		else
			return -9; // 接收错误
	}
	// 对ICMP回应包进行解析
	int time = decode_resp(recvbuf,bread,&from, tid);
	// 如果可以ping通,则返回发送ICMP请求包到接收ICMP回应包的时间,否则返回-1
	if( time >= 0 ){
		*ip = ntohl(from.sin_addr.S_un.S_addr);
		return time;
	}
	else{
		return -1;
	}
}


// 接收ICMP回应包的线程
DWORD WINAPI RecvThreadProc(void *param)
{
	int count = 0;
	ThreadStruct *unionStruct = (ThreadStruct *)param;			// 参数为ThreadStruct,即线程数量
	DWORD startTime = GetTickCount();							// 记录开始时间
	DWORD timeout = unionStruct->timeout * 2;					// 超时时间加长
	SOCKET sockRaw = unionStruct->s;							// 设置套接字
	std::map<unsigned long, PingPair*> *ips = unionStruct->ips;	// 设置要执行批量ping操作的IP地址
	DWORD tid = unionStruct->tid;								// 设置线程ID
	// 如果批量ping操作未完成,并且没有超时,则调用RecvIcmp()函数接收一个IP地址的响应包
	std::map<unsigned long, PingPair*>::iterator itr;
	while( !*(unionStruct->sendCompleted) || GetTickCount() - startTime < timeout){
		unsigned long ip;
		int ret = RecvIcmp(sockRaw, &ip, tid);				// 接收一个IP的ICMP响应包
		if(ret < 0){
			continue;
		}
		if( (itr = ips->find(ip)) != ips->end() && !itr->second->flag){
			QueryPerformanceCounter( &(itr->second->endtime) );		// 获取结束时间
			itr->second->flag = true;								// 设置在线标识
		}
	}

	return 0;
}


// ping一组设备
int pings(std::map<unsigned long, PingPair*> &ips, DWORD timeout)
{
	SOCKET s = CreateSocket(timeout);		// 创建ping操作使用的套接字
	if(s == INVALID_SOCKET){				// 如果创建失败,则返回
		return -1;
	}
	// 准备执行批量ping操作的T
	ThreadStruct unionStruct;
	unionStruct.ips = &ips;					// 要执行ping操作的IP地址映射表
	unionStruct.s = s;				    	// 发送和接收ICMP数据包的套接字
	unionStruct.timeout = timeout;		    // 超时时间
	unionStruct.tid = GetCurrentThreadId();	// 线程ID
	unionStruct.sendCompleted = new bool(false);		// 标识为未发送完成
	// 创建批量ping操作线程,线程函数为RecvThreadProc,参数为unionStruct
	DWORD tid;
	HANDLE handle = CreateThread(NULL, 0, RecvThreadProc, &unionStruct, 0, &tid);
	// 依次向ips中所有IP地址发送
	std::map<unsigned long, PingPair*>::iterator itr;
	for(itr = ips.begin();itr != ips.end();itr++){
		SendIcmp(s, itr->first);							// 发送ICMP请求包
		QueryPerformanceCounter( &itr->second->starttime );	// 记录初始时间
		Sleep(10);
	}
	// 因为ICMP是基于不可靠的UDP协议的
	// 为了防止目标IP没有收到ICMP请求包,这里再发送一次
	for(itr = ips.begin(); itr != ips.end(); itr++){
		SendIcmp(s, itr->first); // 发出所有数据
		Sleep(10);
	}
	// 将发送完成标识设置为true
	*(unionStruct.sendCompleted) = true;
	// 等待接收线程返回
	DWORD ret = WaitForSingleObject(handle, timeout * 3);
	// 结束线程
	if(ret == WAIT_TIMEOUT)	{
		printf("Kill Thread\n");
		TerminateThread(handle, 0);
	}
	CloseHandle(handle);							// 关闭线程句柄
	DestroySocket(s);								// 释放套接字
	// 获取CPU每秒钟跑几个ticks
	LARGE_INTEGER ticksPerSecond;
	QueryPerformanceFrequency(&ticksPerSecond);
	// 依次对所有IP地址进行处理
	for(itr = ips.begin();itr != ips.end();itr++){
		// 如果在线(flag=true),则记录执行ping操作的时间
		if(itr->second->flag == true){
			double elapsed = ((double)(itr->second->endtime.QuadPart - itr->second->starttime.QuadPart) / ticksPerSecond.QuadPart); // 经过的时间, 依自己程式需求选择精准度
			if(elapsed <= 0)
				elapsed = 0;
			itr->second->period = (int)(elapsed*1000);
		}
	}
	delete unionStruct.sendCompleted;
	return 0;
}

// 计算子网地址为NetAddr和子网掩码为NetMask的子网中包含的所有IP地址列表
list<string> FillSubnet(string NetAddr, string NetMask)
{
	list<string> IpList;
	// 将网络地址和子网掩码从网络字节顺序转换为主机字节顺序
	unsigned long _inetaddr = ntohl(inet_addr(NetAddr.c_str()));
	unsigned long _inetmask = ntohl(inet_addr(NetMask.c_str()));
	// 计算网络地址和广播地址
	unsigned long first_netaddr = _inetaddr & _inetmask;
	unsigned long broadcast = _inetaddr | ~_inetmask;
	// 计算子网中包含有效IP地址的数量
	long num = broadcast - first_netaddr - 1;
	for(unsigned long i=first_netaddr+1; i<broadcast; i++){
		// 保存IP地址的结构体
		in_addr IPAddr;
		IPAddr.S_un.S_addr = ntohl(i);
		// 添加每个IP地址到IpList中
		IpList.push_back(inet_ntoa(IPAddr));
	}
	return IpList;
}

list<string> ScanSubnet(string NetAddr, string NetMask, DWORD timeOut)
{
	// 计算子网中的IP地址列表
	list<string> IpList = FillSubnet(NetAddr, NetMask);
	// 将IpList转换成用来执行ping操作的所有IP地址ipAll
	std::map<unsigned long, PingPair*> ipAll;
	list<string>::iterator IpItr;
	// 将IpList转换为ipAll,为调用pings()函数准备数据
	for(IpItr = IpList.begin(); IpItr != IpList.end(); IpItr++){
		string ip = *IpItr;
		if(ip.empty())		// 如果设备IP地址为空,则不处理
			continue;
		unsigned int uip = ntohl(inet_addr(ip.c_str()));
		PingPair *p = new PingPair(uip);
		ipAll[uip] = p;
	}
	// 执行批量ping操作
	pings(ipAll, timeOut);
	// 将活动IP地址保存在ActiveIpList中
	list<string> ActiveIpList;
	std::map<unsigned long, PingPair*>::iterator ipItr;
	for(ipItr=ipAll.begin();ipItr!=ipAll.end();ipItr++){
		if(ipItr->second->flag){
			in_addr IPAddr;
			IPAddr.S_un.S_addr = ntohl(ipItr->second->ip);
			// 将活动IP地址保存在ActiveIpList中
			ActiveIpList.push_back(inet_ntoa(IPAddr));
		}
		delete ipItr->second;
	}
	return ActiveIpList;
}

int main()
{
    const int argc = 3;
    char * argv[] = {"", "192.168.0.1", "255.255.255.0"};
	if(argc != 3)	{
		printf("参数数量不正确。请指定要ping的子网的子网地址和子网掩码。\n");
		return -1;
	}
	// 执行ping操作
	printf("ping subnet: %s, %s...\n", argv[1], argv[2]);
	// 扫描子网
	list<string> ActiveIpList = ScanSubnet(argv[1], argv[2], 500);
	// 显示所有在线IP地址
	printf("The Active IP Address is below:\n");
	list<string>::iterator IpItr;
	for(IpItr = ActiveIpList.begin(); IpItr != ActiveIpList.end(); IpItr++){
		string ip = *IpItr;
		if(ip.empty())		// 如果设备IP地址为空,则不处理
			continue;
		printf("%s\n", ip.c_str());
	}
	system("pause");
	return 0;
}


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章