C++ Builder Snippets  

IMCP-Ping an eine IP-Adresse senden:
//---------------------------------------------------------------------------
#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;
}

© '99-2001 by S. Kreutzmann