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 << "发送失败!" <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);
}

结果

PING程序_第1张图片

你可能感兴趣的:(WinSock)