//---------------------------------------------------------------------------
#include <winsock.h>
// Definition der IP-Optionenstruktur
typedef struct tagIPINFO
{
BYTE bTimeToLive; // Time To Live
BYTE bTypeOfService; // Type Of Service
BYTE bIpFlags; // IP-Flags
BYTE OptSize; // Grösse der Options Data Buffers
BYTE FAR *Options; // Zeiger auf Options Data Buffer
} IPINFO, *PIPINFO;
// Definition der ICMP-Echo Antwortstruktur
typedef struct tagICMPECHO
{
DWORD dwSource; // Zieladresse
DWORD dwStatus; // IP-Status
DWORD dwRTTime; // Round Trip Time in Millisekunden
WORD wDataSize; // Grösse des Antwort-Buffers
WORD wReserved;
void FAR *pData; // Zeiger auf die Antwort-Daten
IPINFO ipInfo; // Antwort-Optionen
} ICMPECHO, *PICMPECHO;
// Zeiger auf die Funktionen aus der ICMP.DLL deklarieren:
typedef HANDLE (WINAPI *PF_CMPCREATEFILE)(VOID);
typedef BOOL (WINAPI *PF_ICMPCLOSEHANDLE)(HANDLE);
typedef DWORD (WINAPI *PF_ICMPSENDECHO)(HANDLE,DWORD,LPVOID,WORD,
PIPINFO,LPVOID,DWORD,DWORD);
//---------------------------------------------------------------------------
// Funktion PingHost() sendet ein IMCP-Echo Request (Ping) an den Rechner
// mit der im Parameter slAddress übergebenen Adresse (oder Namen)
//---------------------------------------------------------------------------
// Übergabeparameter:
//
// AnsiString slAddress : IP-Adresse oder Name des Zielrechners
// TStrings* pStrings : Zeiger auf eine TStrings-Instanz für die
// Ausgabe von Statusmeldungen
//---------------------------------------------------------------------------
// Rückgabewert: : Round Trip Time des Echo Request (die Zeit von dem
// Anfragezeitpunkt bis zum Empfang der Antwort)
// in Millisekunden bei erfolgreicher Ausführung oder
// -1 beim Auftreten von Fehlern
//---------------------------------------------------------------------------
// Beispielaufrufe:
//
// int ilTripTime = PingHost("xxx.xxx.xxx.xxx", Memo1->Lines);
// int ilTripTime = PingHost("test_host", NULL);
//---------------------------------------------------------------------------
int PingHost(AnsiString slAddress, TStrings* pStrings)
{
// Stringsliste leeren:
if(pStrings) pStrings->Clear();
// ICMP.DLL laden:
HANDLE hIcmp = LoadLibrary("ICMP.DLL");
if(hIcmp == NULL)
{
if(pStrings) pStrings->Add("Could not load ICMP.DLL");
return -1;
}
// Zeiger auf die Funktionen besorgen:
PF_CMPCREATEFILE pfIcmpCreateFile = (PF_CMPCREATEFILE)
GetProcAddress(hIcmp, "IcmpCreateFile");
PF_ICMPCLOSEHANDLE pfIcmpCloseHandle = (PF_ICMPCLOSEHANDLE)
GetProcAddress(hIcmp,"IcmpCloseHandle");
PF_ICMPSENDECHO pfIcmpSendEcho = (PF_ICMPSENDECHO)
GetProcAddress(hIcmp,"IcmpSendEcho");
// Funktionszeiger prüfen:
if (pfIcmpCreateFile == NULL || pfIcmpCloseHandle == NULL ||
pfIcmpSendEcho == NULL)
{
if(pStrings) pStrings->Add("Error getting ICMP proc address");
FreeLibrary(hIcmp);
return -1;
}
// WinSock initialisieren
WSADATA wsaData;
int ilRetVal = WSAStartup(0x0101, &wsaData );
if(ilRetVal)
{
if(pStrings)
pStrings->Add("Winsock-Initialsierungsfehler: " + IntToStr(ilRetVal));
WSACleanup();
FreeLibrary(hIcmp);
return -1;
}
// Check WinSock version
if(0x0101 != wsaData.wVersion)
{
if(pStrings)
pStrings->Add("Fehler: Winsock Version 1.1 oder höher nicht vorhanden !");
WSACleanup();
FreeLibrary(hIcmp);
return -1;
}
// Prüfen, ob es sich bei der Zieladresse um IP-Adresse handelt und
// ggf. den die Adresse zum Namen ermitteln:
struct in_addr iaDest; // Struktur für die Internet-Adresse
iaDest.s_addr = inet_addr(slAddress.c_str());
LPHOSTENT pHost; // Zeiger auf die Host Entry Struktur
if (iaDest.s_addr == INADDR_NONE) pHost = gethostbyname(slAddress.c_str());
else pHost = gethostbyaddr((BYTE *)&iaDest, sizeof(struct in_addr), AF_INET);
if(pHost == NULL)
{
if(pStrings)
pStrings->Add("Fehler: Adresse " + slAddress + " wurde nicht gefunden !");
WSACleanup();
FreeLibrary(hIcmp);
return -1;
}
if(pStrings)
pStrings->Add("Ping an " + AnsiString(pHost->h_name) + "[" +
AnsiString(inet_ntoa((*(LPIN_ADDR)pHost->h_addr_list[0]))) + "]");
// IP-Adresse kopieren
DWORD* pAddress = (DWORD*)(*pHost->h_addr_list);
// ICMP Echo Request Handle besorgen:
HANDLE hIcmpFile = pfIcmpCreateFile();
ICMPECHO icmpEcho; // ICMP-Echo Antwortbuffer
IPINFO ipInfo; // IP-Optionenstruktur
int ilTimeSum = 0; // Summe der Round Trip Time-Daten
int ilCount = 0; // Anzahl der Round Trip Time-Daten
for (int ilPingNo = 0; ilPingNo < 3; ilPingNo++)
{
// Default-Werte festlegen:
::ZeroMemory(&ipInfo, sizeof(ipInfo));
ipInfo.bTimeToLive = 255;
// ICMP Echo anfordern:
pfIcmpSendEcho(hIcmpFile, // Handle von IcmpCreateFile()
*pAddress, // Ziel-IP Addresse
NULL, // Zeiger auf den Buffer mit den
// zu sendenden Daten
0, // Buffergrösse in Bytes
&ipInfo, // Request-Optionen
&icmpEcho, // Antwort-Buffer
sizeof(struct tagICMPECHO), // Buffergrösse
5000); // Max. Wartezeit in Millisekunden
// Ergebnisse anzeigen:
iaDest.s_addr = icmpEcho.dwSource;
if(pStrings)
{
AnsiString slMessage = "Antwort von "+AnsiString(
inet_ntoa(iaDest))+ ": Zeit=" + IntToStr(icmpEcho.dwRTTime) +
" ms, Time to Live=" + IntToStr(icmpEcho.ipInfo.bTimeToLive) + " ms";
pStrings->Add(slMessage);
}
// falls Fehler aufgetreten:
if(icmpEcho.dwStatus)
{
if(pStrings)
pStrings->Add("Fehler: IcmpEcho-Status=" + IntToStr(icmpEcho.dwStatus));
break;
}
ilTimeSum += icmpEcho.dwRTTime;
ilCount++;
if(ilPingNo < 2) Sleep(200);
}
// Echo-Request File Handle schliessen:
pfIcmpCloseHandle(hIcmpFile);
// ICMP.DLL freigeben:
FreeLibrary(hIcmp);
// Winsock schliessen:
WSACleanup();
// Den Mittelwert aller Round Trip Times zurückgeben:
return ilRetVal = ilCount ? ilTimeSum/ilCount : -1;
}
|