vc实现ping

//ping.h

#ifndef _CPING_H_

#define _CPING_H_

#include <Winsock2.h>

#include <Windows.h>

#pragma pack(1)



#define ICMP_ECHOREPLY	0

#define ICMP_ECHOREQ	8

#define REQ_DATASIZE	32		// Echo 请求数据的大小



class CPing

{

public:

	//ping host, nRetries-ping次数

	bool Ping(LPCSTR pstrHost, UINT nRetries = 4);



	void Result(int* nElapseTime, float* fMissPack = NULL, u_char* cTTL = NULL);

	//void Result(CPing::REQ_RESULT& result);



private:

	int  WaitForEchoReply(SOCKET s);

	//ICMP回应的请求和回答函数

	int		SendEchoRequest(SOCKET, LPSOCKADDR_IN);

	DWORD	RecvEchoReply(SOCKET, LPSOCKADDR_IN, u_char *);

	u_short in_cksum(u_short *addr, int len);



private:

	struct REQ_RESULT

	{

		int			nElapseTime;	//请求响应时间。

		u_char		cTTL;			//请求TTL(生存时间)

		float		fMissPack;	//丢包率

	};



	REQ_RESULT m_Result;

};



// IP Header -- RFC 791

typedef struct tagIPHDR

{

	u_char  VIHL;			// Version and IHL

	u_char	TOS;			// Type Of Service

	short	TotLen;			// Total Length

	short	ID;				// Identification

	short	FlagOff;		// Flags and Fragment Offset

	u_char	TTL;			// Time To Live

	u_char	Protocol;		// Protocol

	u_short	Checksum;		// Checksum

	struct	in_addr iaSrc;	// Internet Address - Source

	struct	in_addr iaDst;	// Internet Address - Destination

}IPHDR, *PIPHDR;





// ICMP Header - RFC 792

typedef struct tagICMPHDR

{

	u_char	Type;			// Type

	u_char	Code;			// Code

	u_short	Checksum;		// Checksum

	u_short	ID;				// Identification

	u_short	Seq;			// Sequence

	char	Data;			// Data

}ICMPHDR, *PICMPHDR;







// ICMP Echo Request

typedef struct tagECHOREQUEST

{

	ICMPHDR icmpHdr;

	DWORD	dwTime;

	char	cData[REQ_DATASIZE];

}ECHOREQUEST, *PECHOREQUEST;





// ICMP Echo Reply

typedef struct tagECHOREPLY

{

	IPHDR	ipHdr;

	ECHOREQUEST	echoRequest;

	char    cFiller[256];

}ECHOREPLY, *PECHOREPLY;



#pragma pack()



#endif

  

//ping.cpp

#include "ping.h"



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



bool CPing::Ping(LPCSTR pstrHost, UINT nRetries)

{

	//创建一个Raw套节字

	SOCKET rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

	if (rawSocket == INVALID_SOCKET) 

	{

		int err = WSAGetLastError();

		return false;

	}

	int nNetTimeout = 1000;//1秒 

	//发送时限

	setsockopt(rawSocket, SOL_SOCKET, SO_SNDTIMEO, (char *)&nNetTimeout,sizeof(int));

	//接收时限

	setsockopt(rawSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout,sizeof(int));



	//获得主机信息

	LPHOSTENT lpHost = gethostbyname(pstrHost);

	if (lpHost == NULL)

	{

		return false;

	}

	

	//构造目标套节字地址信息

	struct    sockaddr_in saDest;

	struct    sockaddr_in saSrc;

	saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));

	saDest.sin_family = AF_INET;

	saDest.sin_port = 3077;//0;



	DWORD	 dwTimeSent;

	u_char   cTTL;

	int		nRet;

	int		nRecvNum = 0;

	int		nTotalTime = 0;



	//多次ping

	for (UINT nLoop = 0; nLoop < nRetries; ++nLoop)

	{

		//发送ICMP回应请求

		if ((nRet = SendEchoRequest(rawSocket, &saDest)) < 0)

		{

			break;

		}



		if ((nRet = WaitForEchoReply(rawSocket)) == SOCKET_ERROR)

		{

			break;

		}

		if (nRet)

		{

			//获得回应

			if ( (dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL)) < 0)

			{

				nRet = dwTimeSent;

				break;

			}

			//计算时间

			nTotalTime += GetTickCount() - dwTimeSent;

			//Sleep(1000);

			++nRecvNum;

		}

	}

	closesocket(rawSocket);

	if (nRecvNum > 0 && nRet >= 0)

	{

		m_Result.nElapseTime = nTotalTime/nRetries;

		m_Result.cTTL = cTTL;

		m_Result.fMissPack = (float)(nRetries - nRecvNum)/nRetries;

		return true;

	}



	return false;

}



//发送ICMPECHO数据包请求

int CPing::SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr) 

{

	static ECHOREQUEST echoReq;

	static int nId = 1;

	static int nSeq = 1;

	int nRet;



	//构造回应请求

	echoReq.icmpHdr.Type		= ICMP_ECHOREQ;

	echoReq.icmpHdr.Code		= 0;

	echoReq.icmpHdr.Checksum	= 0;

	echoReq.icmpHdr.ID			= nId++;

	echoReq.icmpHdr.Seq			= nSeq++;



	for (nRet = 0; nRet < REQ_DATASIZE; nRet++)

		echoReq.cData[nRet] = ' '+nRet;



	//保存发送时间

	echoReq.dwTime	= GetTickCount();



	echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST));



	//发送请求

	nRet = sendto(s,						

				 (LPSTR)&echoReq,			

				 sizeof(ECHOREQUEST),

				 0,							

				 (LPSOCKADDR)lpstToAddr, 

				 sizeof(SOCKADDR_IN));   

	//检查返回值

	if (nRet == SOCKET_ERROR) 

	{

	}



	return (nRet);

}



//接收ICMPECHO数据包回应

DWORD CPing::RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL) 

{

	ECHOREPLY echoReply;

	int nRet;

	int nAddrLen = sizeof(struct sockaddr_in);



	//接收请求回应

	nRet = recvfrom(s,					

					(LPSTR)&echoReply,	

					sizeof(ECHOREPLY),	

					0,					

					(LPSOCKADDR)lpsaFrom,

					&nAddrLen);			



	//检查返回值

	if (nRet == SOCKET_ERROR) 

	{

		return nRet;

	}



	//返回发送的时间

	*pTTL = echoReply.ipHdr.TTL;



	return(echoReply.echoRequest.dwTime);   		

}



//等待回应

int CPing::WaitForEchoReply(SOCKET s)

{

	struct timeval Timeout;

	fd_set readfds;



	readfds.fd_count = 1;

	readfds.fd_array[0] = s;

	Timeout.tv_sec = 1;

    Timeout.tv_usec = 0;



	return(select(1, &readfds, NULL, NULL, &Timeout));

}



//转换地址

u_short CPing::in_cksum(u_short *addr, int len)

{

	register int nleft = len;

	register u_short *w = addr;

	register u_short answer;

	register int sum = 0;



	while( nleft > 1 )  {

		sum += *w++;

		nleft -= 2;

	}



	if( nleft == 1 ) {

		u_short	u = 0;



		*(u_char *)(&u) = *(u_char *)w ;

		sum += u;

	}



	sum = (sum >> 16) + (sum & 0xffff);	

	sum += (sum >> 16);			

	answer = ~sum;				

	return (answer);

}



void CPing::Result(int* nElapseTime, float* fMissPack, u_char* cTTL)

{

	if (nElapseTime)

	{

		*nElapseTime = m_Result.nElapseTime;

	}

	if (fMissPack)

	{

		*fMissPack = m_Result.fMissPack;

	}

	if (cTTL)

	{

		*cTTL = m_Result.cTTL;

	}

}

  

//main.cpp

#include <stdlib.h>

#include <iostream>

#include <string>

#include "ping.h"



int main(int argn, char *argv[])

{

	WORD wVersionRequested;

	WSADATA wsaData;

	int err;



	wVersionRequested = MAKEWORD( 1, 1 );



	err = WSAStartup( wVersionRequested, &wsaData );



	CPing ping;

	bool bResult = false;

	if (argn == 2)

	{

		bResult = ping.Ping(argv[1]);

	}

	else

	{

		bResult = ping.Ping("www.baidu.com");

	}

	

	std::cout << "result : " << bResult << std::endl;

	if (bResult)

	{

		int nTime;

		u_char nTTL;

		float fMiss;

		ping.Result(&nTime, &fMiss, &nTTL);



		std::cout << "time : " << nTime << " TTL : " << (int)nTTL << " miss : " << fMiss*100 << "% " << std::endl;

	}

	return 0;

}

  

你可能感兴趣的:(ping)