PING程序

代碼 

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include "iostream"
#include "winsock2.h"
#include "string.h"
#pragma comment(lib,"WS2_32")
#define DATALEN 1012
#define PACKAGENUM 10

using namespace std;
typedef struct icmp_hdr {
	unsigned char icmp_type;   //icmp包類型
	unsigned char icmp_code;   //代碼
	unsigned short icmp_checksum;  //校驗和
	unsigned short icmp_id;  //標識
	unsigned short icmp_sequence;  //序列號
	unsigned long icmp_timestamp;  //時間戳
} IcmpHeader;
unsigned short checksum(unsigned short *buff, int size);

int main(int argc, char **argv) {
	WSADATA wsaData;
	int ret;
	if ((ret = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) {
		cout << "初始化WinSock2.2出錯!";
		return -1;
	}
	char szDestIp[256] = { 0 };
	/*
	if (argc < 2) {
		cout << "\n用法:ping IP 地址|域名\n";
		return -1;
	}
	strcpy(szDestIp, argv[1]);     //從命令行讀取ip地址或域名
	*/
    cout << "請輸入目的地址:" << endl;
	cin.getline(szDestIp, sizeof(szDestIp));
	
	//解析域名
	unsigned long ulDestIP = inet_addr(szDestIp);
	if (ulDestIP == INADDR_NONE) {
		hostent* pHostent = gethostbyname(szDestIp);
		if (pHostent != NULL) {
			ulDestIP = (*(in_addr*)pHostent->h_addr).s_addr;
		}
		else {
			cout << "無法解析主機名" << endl;
			WSACleanup();
			return -1;
		}
		/*
		char **pptr;
		pptr = pHostent->h_addr_list;
		while (*pptr != NULL) {
			cout << inet_ntoa(*(struct in_addr *)(*pptr)) << endl; pptr++;
		}*/
	}
	
	SOCKET sRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);   //收發icmp包的原始套接字
	int nTime = 1000;
	ret = setsockopt(sRaw, SOL_SOCKET, SO_RCVTIMEO, (char *)&nTime, sizeof(nTime));
	if (ret == SOCKET_ERROR) {
		cout << "套接字選項設置出錯" << endl;
		return -1;
	}

	SOCKADDR_IN dest;
	dest.sin_family = AF_INET;
	dest.sin_port = htons(0);
	dest.sin_addr.S_un.S_addr = ulDestIP;
	
	char buff[sizeof(IcmpHeader) + DATALEN];
	IcmpHeader *pIcmp = (IcmpHeader *)buff;

	pIcmp->icmp_type = 8;
	pIcmp->icmp_code = 0;
	pIcmp->icmp_id = (unsigned short)GetCurrentProcessId();
	pIcmp->icmp_timestamp = 0;
	pIcmp->icmp_checksum = 0;
	pIcmp->icmp_sequence = 0;
	memset(&buff[sizeof(IcmpHeader)], 'A', DATALEN);   //填充數據部分
	if (connect(sRaw, (SOCKADDR *)&dest, sizeof(dest))!=0){
		cout << "連接失敗!" << endl;
		closesocket(sRaw);
		WSACleanup();
		return -1;
	}

	int nRet, n = 0;
	bool bTimeout;
	unsigned short nSeq = 0;    //發送的ICMP報文的序號
	char recvBuf[32 + DATALEN];
	SOCKADDR_IN from;
	int nLen = sizeof(from);  
	static int nCount = 0;
	IcmpHeader *pRecvIcmp;
	pRecvIcmp = NULL;
	while (TRUE) {
		//cout << nCount << endl;
		if (nCount++ == PACKAGENUM)break;
		pIcmp->icmp_checksum = 0;
		pIcmp->icmp_timestamp = GetTickCount();
		pIcmp->icmp_sequence = nSeq++;
		pIcmp->icmp_checksum = checksum((unsigned short*)buff, sizeof(IcmpHeader) + DATALEN);
		//cout << buff[5] << endl;
		nRet = send(sRaw, buff, sizeof(IcmpHeader) + DATALEN, 0);
		if (nRet == SOCKET_ERROR) {
			cout << "發送失敗!" <<WSAGetLastError()<< endl;
			closesocket(sRaw);
			WSACleanup();
			return -1;
		}
		bTimeout = false;n = 0;
		do {
			n++;
			memset((void *)recvBuf, 0, sizeof(recvBuf));
			nRet = recvfrom(sRaw, recvBuf, sizeof(recvBuf), 0, (sockaddr *)&from, &nLen);
			if (nRet == SOCKET_ERROR) {
				if (WSAGetLastError() == WSAETIMEDOUT) {
					cout << "time out!" << endl;
					bTimeout = true;
					break;
				}
				cout << "接收應答包失敗!" << endl;
				return -1;
			}
			pRecvIcmp = (IcmpHeader *)(recvBuf + 20);  //收到的數據包含20個字節的IP首部,加20是ICMP首部位置
			if (pRecvIcmp->icmp_id != GetCurrentProcessId()) {
				cout << "unexpected message" << endl;
			}
			else break;
		} while (n < 10);
		if (n > 10) {
			cout << "too many icmps!" << endl;
			closesocket(sRaw);
			WSACleanup();
			return -1;
		}
		if (bTimeout)continue;

		int nTick = GetTickCount();
		if (nRet < 20 + sizeof(IcmpHeader)) {
			cout << "too feww bytes from " << inet_ntoa(from.sin_addr) << endl;
			continue;
		}
		else {
			cout << nRet << " bytes from:" << inet_ntoa(from.sin_addr);
			cout << "icmp_seq = " << pRecvIcmp->icmp_sequence;
			cout << " time:" << nTick - pRecvIcmp->icmp_timestamp << " ms" << endl;
			Sleep(1000);
		}
	}
	closesocket(sRaw);
	WSACleanup();
	return 0;
}

unsigned short checksum(unsigned short * buff, int size) {
	unsigned long cksum = 0;
	while (size > 1) {
		cksum += *buff++;
		size -= sizeof(unsigned short);
	}
	if (size)cksum += *(char *)buff;
	cksum = (cksum >> 16) + (cksum & 0xffff);
	cksum += (cksum >> 16);
	return (unsigned short)(~cksum);
}

結果

發佈了37 篇原創文章 · 獲贊 11 · 訪問量 4777
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章