⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ping.cpp

📁 一个用ACE别写的ping 程序
💻 CPP
字号:
// Ping.cpp: implementation of the CPing class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Ping.h"
#include "ace/OS_NS_sys_socket.h"
#include "ace/Log_Msg.h"
#include "ace/OS_NS_sys_time.h"
#include "ace/OS_NS_unistd.h"

//////////////////////////////////////////////////////////////////////
// CPing
//////////////////////////////////////////////////////////////////////

int CPing::PingHost(DWORD dwNetOrderIP,int trynums, int timeout)
{
	CPingObj pingobj;

	if( !pingobj.Init(timeout) )
		return false;

	return pingobj.ping(dwNetOrderIP,trynums);
}


int CPing::PingHost(DWORD dwNetOrderIP,int trynums, int timeout,const void * pPingData,int len)
{
	CPingObj pingobj;

	if( !pingobj.Init(timeout) )
		return false;

	return pingobj.ping(dwNetOrderIP,trynums,pPingData,len);	
}

//////////////////////////////////////////////////////////////////////////
//CPingObj
//////////////////////////////////////////////////////////////////////////


CPingObj::CPingObj()
:m_sockRaw(ACE_INVALID_HANDLE),m_timeout(0)
{

}

CPingObj::~CPingObj()
{
	if( ACE_INVALID_HANDLE != m_sockRaw)
	{
		ACE_OS::closesocket (m_sockRaw);
	}

}


//失败返回0,成功返回其它
int CPingObj::Init(int timeout)
{
	ACE_ASSERT( timeout > 0 );

	m_timeout = timeout;
	
	m_sockRaw = ACE_OS::socket(AF_INET, SOCK_RAW,IPPROTO_ICMP);
	if (m_sockRaw == ACE_INVALID_HANDLE ) 
	{
		return FALSE;
	}

	 if (ACE_OS::setsockopt (m_sockRaw, SOL_SOCKET, SO_SNDTIMEO,
		(char *)&timeout, sizeof(timeout))==SOCKET_ERROR )	
	{
		 ACE_OS::closesocket (m_sockRaw);
		 m_sockRaw = ACE_INVALID_HANDLE;
		return FALSE;
	}
	
	 if (ACE_OS::setsockopt (m_sockRaw, SOL_SOCKET, SO_RCVTIMEO,
		(char *)&timeout, sizeof(timeout))==SOCKET_ERROR )	
	{
		 ACE_OS::closesocket (m_sockRaw);
		 m_sockRaw = ACE_INVALID_HANDLE;
		 return FALSE;
	}

	 return true;
}

int CPingObj::ping(DWORD dwNetOrderIP,int trynums,const void * pPingData,int len)
{
	ACE_ASSERT( trynums > 0 );

	return CPingFunc::ping(dwNetOrderIP,trynums,m_timeout,pPingData,len,m_sockRaw);
}

//由程序随机构成pPingData和len
int CPingObj::ping(DWORD dwNetOrderIP,int trynums)
{
	ACE_Time_Value curTime = ACE_OS::gettimeofday();
	srand(curTime.sec());

	int buf[8];
	for(int i = 0; i < sizeof(buf)/sizeof(buf[0]); i++)
	{
		buf[i] = rand();	
	}

	return ping(dwNetOrderIP,trynums,buf,sizeof(buf));
}


//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////


#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0

#define ICMP_MIN 8 // minimum 8 byte icmp packet (just header)

#pragma pack(1)

/* The IP header */
typedef struct _iphdr {
	unsigned char h_len:4;          // length of the header
	unsigned char version:4;        // Version of IP
	unsigned char tos;             // Type of service
	unsigned short total_len;      // total length of the packet
	unsigned short ident;          // unique identifier
	unsigned short frag_and_flags; // flags
	unsigned char  ttl; 
	unsigned char proto;           // protocol (TCP, UDP etc)
	unsigned short checksum;       // IP checksum

	unsigned int sourceIP;
	unsigned int destIP;
}IpHeader;

// ICMP header
typedef struct _ihdr {
  BYTE i_type;
  BYTE i_code; /* type sub code */
  ACE_UINT16 i_cksum;

  ACE_UINT16 i_process_id;
  ACE_UINT16 seq;  


}IcmpHeader;

#pragma pack()

//如果ping通,返回非0,
//没有ping通,返回0
int CPingFunc::ping(DWORD dwNetOrderIP,int trynums, int timeout,const void * pPingData,int len,ACE_HANDLE sockRaw)
{
	const int send_icmp_data_len = len+sizeof(IcmpHeader);
	char * icmp_data = new char[send_icmp_data_len];

	const int recv_icmp_data_len = len+sizeof(IpHeader)+sizeof(IcmpHeader)+20;
	char * recvbuf = new char[recv_icmp_data_len];

	static ACE_UINT16 seq = 0;
	++seq;

	ACE_UINT16 processid = (ACE_UINT16)ACE_OS::getpid();

	CPingFunc::fill_icmp_data(icmp_data,processid,seq,pPingData,len);	
	
	SOCKADDR_IN dest;
	
	memset( &dest, 0x00, sizeof(dest) );
	dest.sin_family = AF_INET;
	dest.sin_addr.s_addr = dwNetOrderIP;
	
	int bPingOK = FALSE;
	
	for( int i = 0; i < trynums && bPingOK == FALSE ; i++ )
	{	
		int nsended = ACE_OS::sendto(sockRaw,icmp_data,send_icmp_data_len,
			0,(struct sockaddr*)&dest,sizeof(dest));

		if( nsended < send_icmp_data_len )
			continue;

		ACE_Time_Value curTime = ACE_OS::gettimeofday();
	
		do{	
			struct sockaddr_in from;
			memset(&from,0x00,sizeof(from));
			
			int fromlen = sizeof(from);

			int nreaded = ACE_OS::recvfrom(sockRaw,recvbuf,recv_icmp_data_len,
				0,(struct sockaddr*)&from,&fromlen);
			
			if (nreaded == SOCKET_ERROR)
				break;
			
			if( dwNetOrderIP != from.sin_addr.s_addr  )
				continue;

			if ( decode_resp(recvbuf,nreaded,processid,seq,pPingData,len)==1 )
			{
				bPingOK = TRUE;
				break;
			}	
			else
			{
				curTime = ACE_OS::gettimeofday() - curTime;
			}

		}while( curTime.msec() < timeout );
	}
	
	ACE_OS::closesocket (sockRaw);
	delete []recvbuf;
	delete []icmp_data;	

	return bPingOK;

}

int CPingFunc::decode_resp(const char *buf, int bytes,ACE_UINT16 i_process_id,ACE_UINT16 seq,const void * pPingData,int len)
{
	IpHeader * iphdr = (IpHeader *)buf;

	ACE_UINT16 iphdrlen = iphdr->h_len * 4 ; // number of 32-bit words *4 = bytes
	ACE_UINT16 total_len = ACE_NTOHS(iphdr->total_len);
  
	if (bytes  < iphdrlen + ICMP_MIN + len) 
	{
		return FALSE;
	}

	IcmpHeader * icmphdr = (IcmpHeader*)(buf + iphdrlen);

	if (icmphdr->i_type != ICMP_ECHOREPLY) 
	{	
		return FALSE;
	}

	if( icmphdr->i_process_id != i_process_id 
		|| icmphdr->seq != seq )
	{	
		return FALSE;
	}

	return (memcmp((char *)icmphdr+sizeof(IcmpHeader),pPingData,len)==0);
}



/* 
	Helper function to fill in various stuff in our ICMP request.
*/
void CPingFunc::fill_icmp_data(char * icmp_data,ACE_UINT16 i_process_id,ACE_UINT16 seq,const void * pPingData,int len)
{
	IcmpHeader *icmp_hdr = (IcmpHeader*)icmp_data;
	
	icmp_hdr->i_type = ICMP_ECHO;
	icmp_hdr->i_code = 0;
	icmp_hdr->i_cksum = 0;

	icmp_hdr->i_process_id = i_process_id;
	icmp_hdr->seq = seq;

	if (pPingData && len > 0)
	{
		memcpy(icmp_data + sizeof(IcmpHeader),pPingData,len);
	}
	
	icmp_hdr->i_cksum = checksum((ACE_UINT16 *)icmp_data,len+sizeof(IcmpHeader));

	return;
}

ACE_UINT16 CPingFunc::checksum(const ACE_UINT16 *buffer, int size) 
{	
	unsigned long cksum=0;
	
	while(size >1) {
		cksum+=*buffer++;
		size -=sizeof(ACE_UINT16);
	}
	
	if(size ) {
		cksum += *(BYTE*)buffer;
	}
	
	cksum = (cksum >> 16) + (cksum & 0xffff);
	cksum += (cksum >>16);
	return (ACE_UINT16)(~cksum);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -