与窗口类结合使用
#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 );
}