?? 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 + -