掃描子網中的地址+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;
}


 

 

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