与窗口类结合使用
#pragma once #define ICMP_ECHO 8 #define ICMP_ECHOREPLY 0 #define ICMP_MIN 8 // minimum 8 byte icmp packet (just header) #define STATUS_FAILED 0xFFFF #define DEF_PACKET_SIZE 32 #define DEF_PACKET_NUMBER 4 /* ·¢ËÍÊý¾Ý±¨µÄ¸öÊý */ #define MAX_PACKET 1024 #define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s)) #define xfree(p) HeapFree (GetProcessHeap(),0,(p)) /* The IP header */ typedef struct iphdr { unsigned int h_len:4; // length of the header unsigned int 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 icmphdr { BYTE i_type; //ICMPÀàÐÍÂ룬»ØËÍÇëÇóµÄÀàÐÍÂëΪ8 BYTE i_code; /* type sub code */ USHORT i_cksum; //УÑéºÍ USHORT i_id; //ICMPÊý¾Ý±¨IDºÅ USHORT i_seq; //ICMPÊý¾Ý±¨ÐòÁкŠ/* This is not the std header, but we reserve space for time */ ULONG timestamp; //ʱ¼ä´Á£¬¿ÉÑ¡ }IcmpHeader; class CPing { public: CPing(void); ~CPing(void); private: void fill_icmp_data(char *, int); USHORT checksum(USHORT *, int); int decode_resp(char *,int ,struct sockaddr_in *); void printResult( HWND hWnd ); public: void DoPing(int times,LPTSTR url,HWND hWnd); private: WSADATA wsaData; SOCKET sockRaw; struct sockaddr_in dest,from; struct hostent * hp; int bread,datasize; int fromlen; int timeout; int statistic; char *dest_ip; char *icmp_data; char *recvbuf; unsigned int addr; USHORT seq_no; char szResult[256]; };
#pragma pack(4) #include "stdafx.h" #include "winsock2.h" #pragma comment(lib,"Ws2_32.lib") #include "stdlib.h" #include "stdio.h" #include "Ping.h" CPing::CPing(void) { timeout = 1000; statistic = 0; /* ÓÃÓÚͳ¼Æ½á¹û */ addr=0; seq_no = 0; //szResult = "E";//ÓÃÈÎÒâ×Ö·û³õʼ»¯ datasize = DEF_PACKET_SIZE; fromlen = sizeof(from); } CPing::~CPing(void) { } //private method int CPing::decode_resp(char *buf, int bytes,struct sockaddr_in *from) { IpHeader *iphdr; IcmpHeader *icmphdr; unsigned short iphdrlen; iphdr = (IpHeader *)buf; iphdrlen = (iphdr->h_len) * 4 ; // number of 32-bit words *4 = bytes if (bytes < iphdrlen + ICMP_MIN) { wsprintf(szResult,TEXT("Too few bytes from %s /r/r/n"),inet_ntoa(from->sin_addr)); } icmphdr = (IcmpHeader*)(buf + iphdrlen); if (icmphdr->i_type != ICMP_ECHOREPLY) { wsprintf(szResult,TEXT("non-echo type %d recvd /r/r/n"),icmphdr->i_type); return 1; } if (icmphdr->i_id != (USHORT)GetCurrentProcessId()) { wsprintf(szResult,TEXT("someone else''s packet! /r/r/n") ); return 1; } // printf("%d bytes from %s:",bytes, inet_ntoa(from->sin_addr)); // printf(" icmp_seq = %d. ",icmphdr->i_seq); // printf(" time: %d ms ",GetTickCount()-icmphdr->timestamp); // printf("/n"); wsprintf(szResult,TEXT("%d bytes from %s: icmp_seq = %d. time: %d ms /r/r/n"),bytes,inet_ntoa(from->sin_addr),icmphdr->i_seq,GetTickCount()-icmphdr->timestamp); return 0; } USHORT CPing::checksum(USHORT *buffer, int size) { unsigned long cksum=0; while(size >1) { cksum+=*buffer++; size -=sizeof(USHORT); } if(size) { cksum += *(UCHAR*)buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum); } /* Helper function to fill in various stuff in our ICMP request. */ void CPing::fill_icmp_data(char * icmp_data, int datasize) { IcmpHeader *icmp_hdr; char *datapart; icmp_hdr = (IcmpHeader*)icmp_data; icmp_hdr->i_type = ICMP_ECHO; icmp_hdr->i_code = 0; icmp_hdr->i_id = (USHORT)GetCurrentProcessId(); icmp_hdr->i_cksum = 0; icmp_hdr->i_seq = 0; datapart = icmp_data + sizeof(IcmpHeader); // // Place some junk in the buffer. // memset(datapart,'E', datasize - sizeof(IcmpHeader)); } void CPing::printResult( HWND hWnd ) { int nLen = ::GetWindowTextLength( hWnd ); ::SendMessage(hWnd,EM_SETSEL,nLen,-1); ::SendMessage(hWnd,EM_REPLACESEL,0,(LPARAM)szResult); } //public method void CPing::DoPing( int times,LPTSTR url,HWND hWnd ) { if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0) { //ΪÁËÔÚÓ¦ÓóÌÐòµ±Öе÷ÓÃÈκÎÒ»¸öWinsock APIº¯Êý£¬Ê×ÏȵÚÒ»¼þÊÂÇé¾ÍÊDZØÐëͨ¹ýWSAStartupº¯ÊýÍê³É¶ÔWinsock·þÎñµÄ³õʼ»¯ wsprintf(szResult,"WSAStartup failed: %d /r/r/n",GetLastError()); printResult( hWnd ); return; } sockRaw = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL, 0,WSA_FLAG_OVERLAPPED);//´´½¨Ò»¸öÓëÖ¸¶¨´«ËÍ·þÎñÌṩÕßÀ¦°óµÄÌ×½Ó¿Ú£¬¿ÉÑ¡µØ´´½¨ºÍ/»ò¼ÓÈëÒ»¸öÌ×½Ó¿Ú×é;·µ»ØÐÂÌ×½Ó¿ÚÃèÊö×Ö£¬»òINVALID_SOCKET // //×¢£ºÎªÁËʹÓ÷¢ËͽÓÊÕ³¬Ê±ÉèÖÃ(¼´ÉèÖÃSO_RCVTIMEO, SO_SNDTIMEO)£¬ // ±ØÐ뽫±ê־λÉèΪWSA_FLAG_OVERLAPPED ! // if (sockRaw == INVALID_SOCKET) { wsprintf(szResult,"WSASocket() failed: %d /r/r/n",WSAGetLastError()); printResult( hWnd ); return; } bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout)); //ÉèÖýÓÊÕ³¬Ê±,sets a socket option,return zero or a value of SOCKET_ERROR if(bread == SOCKET_ERROR) { wsprintf(szResult,"failed to set recv timeout: %d /r/r/n",WSAGetLastError()); printResult( hWnd ); return; } timeout = 1000; bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout)); //·¢Ëͳ¬Ê± if(bread == SOCKET_ERROR) { wsprintf(szResult,"failed to set send timeout: %d /r/r/n",WSAGetLastError()); printResult( hWnd ); return; } memset(&dest,0,sizeof(dest)); hp = gethostbyname( (const char*)url ); if (!hp) { addr = inet_addr( (const char*)url ); //µØÖ·¸ñʽת»» } if ((!hp) && (addr == INADDR_NONE) ) { wsprintf(szResult,"Unable to resolve %s /r/r/n",url); printResult( hWnd ); return; } if (hp != NULL) memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length); else dest.sin_addr.s_addr = addr; if (hp) dest.sin_family = hp->h_addrtype; else dest.sin_family = AF_INET; dest_ip = inet_ntoa(dest.sin_addr); //This function converts an (Ipv4) Internet network address into a string in Internet standard dotted format datasize += sizeof(IcmpHeader); icmp_data = (char*)xmalloc(MAX_PACKET); recvbuf = (char*)xmalloc(MAX_PACKET); if (!icmp_data) { wsprintf(szResult,"HeapAlloc failed %d /r/r/n",GetLastError()); printResult( hWnd ); xfree( recvbuf ); xfree( icmp_data ); return; } memset(icmp_data,0,MAX_PACKET); fill_icmp_data(icmp_data,datasize); // //ÏÔʾÌáʾÐÅÏ¢ // wsprintf(szResult,"CPinging %s [%s]..../r/r/n",(LPCSTR)dest_ip,url); printResult( hWnd ); for(int i = 0;i < times;i++ ) { int bwrote; ((IcmpHeader*)icmp_data)->i_cksum = 0; ((IcmpHeader*)icmp_data)->timestamp = GetTickCount(); ((IcmpHeader*)icmp_data)->i_seq = seq_no++; ((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data,datasize); bwrote = sendto( sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest) ); if (bwrote == SOCKET_ERROR) { if (WSAGetLastError() == WSAETIMEDOUT) { wsprintf(szResult,"Request timed out./r/r/n"); printResult( hWnd ); continue; } wsprintf(szResult,"sendto failed: %d /r/r/n",WSAGetLastError()); printResult( hWnd ); xfree( recvbuf ); xfree( icmp_data ); return; } if (bwrote < datasize ) { wsprintf(szResult,"Wrote %d bytes /r/r/n",bwrote); printResult( hWnd ); } bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,&fromlen); if (bread == SOCKET_ERROR) { if (WSAGetLastError() == WSAETIMEDOUT) { wsprintf(szResult,"Request timed out./r/r/n"); printResult( hWnd ); continue; } wsprintf(szResult,"recvfrom failed: %d /r/r/n",WSAGetLastError()); printResult( hWnd ); xfree( recvbuf ); xfree( icmp_data ); return; } if(!decode_resp(recvbuf,bread,&from)) { printResult( hWnd ); statistic++; /* ³É¹¦½ÓÊÕµÄÊýÄ¿++ */ } Sleep(1000); }//for(int i = 0;i<times;i++) wsprintf( szResult,"CPing statistics for %s /r/r/n Packets: Sent = %d,Received = %d, Lost = %d (%2.0f%% loss)/r/r/n", (LPCSTR)dest_ip,times,statistic,(times-statistic),(float)((times-statistic)/times)*100 ); printResult( hWnd ); WSACleanup(); xfree( recvbuf ); xfree( icmp_data ); }