Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Trucos (https://www.clubdelphi.com/foros/forumdisplay.php?f=52)
-   -   Hacer Ping desde código (https://www.clubdelphi.com/foros/showthread.php?t=80851)

escafandra 15-05-2008 07:45:56

Hacer Ping desde código
 
Para hacer un Ping por código y saber si se ha tenido éxito, esta puede ser una solución.

Yo lo utilizo para comprobar que tengo conexión a internet haciendo un Ping a una página estable como google (64.233.187.99). Indudablemente puede tener muchas mas utilidades.

Esta escrito en C++. Las funciones están definidas en esta cabecera (icmpapi.h), dependiendo de vuestro compilador, es posible que dispongáis ya de la cabecera. El mio, C++Builder 5 no las tiene definidas.

Estas funciones están en la librería icmp.dll desde Windows NT y en el XP, ademas se puede acceder a ellas desde iphlpapi.dll. De forma que tendréis que preparar el compilador para que las linke.

Aquí esta la cabecera:

icmpapi.h

Código:

/*
 * Interface to the ICMP functions.
 *
 * Copyright (C) 1999 Francois Gouget
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#ifndef __WINE_ICMPAPI_H
#define __WINE_ICMPAPI_H
 
#ifdef __cplusplus
extern "C" {
#endif


HANDLE WINAPI IcmpCreateFile(
    VOID
    );

BOOL WINAPI IcmpCloseHandle(
    HANDLE  IcmpHandle
    );

DWORD WINAPI IcmpSendEcho(
    HANDLE                IcmpHandle,
    IPAddr                DestinationAddress,
    LPVOID                RequestData,
    WORD                  RequestSize,
    PIP_OPTION_INFORMATION RequestOptions,
    LPVOID                ReplyBuffer,
    DWORD                  ReplySize,
    DWORD                  Timeout
    );


#ifdef __cplusplus
}
#endif

#endif /* __WINE_ICMPAPI_H */

Y el código necesario...

Código:


//------------------------------------------------------------------------------
//  Copyright (C) Escafandra 2008
//  Hacer Ping y conocer el resultado
//  Entrada IP en formato 255.255.255.255
//  Devuelve true si tiene exito o false si hubo un error.
//------------------------------------------------------------------------------
 
#include <winsock2.h>
#include <iphlpapi.h>
#include "icmpapi.h"


bool Ping(char* Addr)
{
    //Formato de Addr NNN.NNN.NNN.NNN

    //Declarar e inicializar variables
    bool Result = true;
    HANDLE hIcmpFile;
    unsigned long ipaddr = INADDR_NONE;
    DWORD dwRetVal = 0;
    char SendData[] = "Data Buffer";
    LPVOID ReplyBuffer = NULL;
    DWORD ReplySize = 0;

    //Obtener IP
    ipaddr = inet_addr(Addr);
    if (ipaddr == INADDR_NONE){
      Result = false;
      return Result;
    }

    hIcmpFile = IcmpCreateFile();
    if (hIcmpFile == INVALID_HANDLE_VALUE) {
      Result = false;
      return Result;
    }
    ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData);
    ReplyBuffer = (VOID*) malloc(ReplySize);
    if (ReplyBuffer == NULL) {
      Result = false;  // No localizacion de memoria...
      return Result;
    }

    // Envia Ping
    dwRetVal = IcmpSendEcho(hIcmpFile, ipaddr, SendData, sizeof(SendData),
        NULL, ReplyBuffer, ReplySize, 1000);

    if (dwRetVal != 0) {
        PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;
        // Detectar Error en Ping (IP_STATUS)
        // ICMP_ECHO_REPLY Structure IP_STATUS code
        // http://msdn2.microsoft.com/en-us/library/aa366053(VS.85).aspx
        if(pEchoReply->Status != 0){
            Result = false;  // Error en Ping el Host no lo recibe....
        }
    }else{
      Result = false;  // Error en IcmpSendEcho localizar con GetLastError()
    }
   
    free(ReplyBuffer);
    return Result;
}

Que le saquéis partido.
Saludos.


EDITO:
Modifico el truco para repetir el ping de forma automática un número de veces pasado como parámetro. En ocasiones un sólo ping no tiene éxito...
Código:

//------------------------------------------------------------------------------
//  Copyright (C) Escafandra 2008
//  Hacer Ping y conocer el resultado
//  Entrada IP en formato 255.255.255.255
//  Devuelve true si tiene exito o false si hubo un error.
//------------------------------------------------------------------------------
#include <winsock2.h>
#include <iphlpapi.h>
#include "icmpapi.h"


bool Ping(char* Addr, int NVeces)
{
    //Formato de Addr NNN.NNN.NNN.NNN

    //Declarar e inicializar variables
    bool Result = true;
    HANDLE hIcmpFile;
    unsigned long ipaddr = INADDR_NONE;
    DWORD dwRetVal = 0;
    char SendData[] = "Data Buffer";
    LPVOID ReplyBuffer = NULL;
    DWORD ReplySize = 0;

    //Obtener IP de Addr
    ipaddr = inet_addr(Addr);
    if (ipaddr == INADDR_NONE){
      Result = false;
      return Result;
    }

    hIcmpFile = IcmpCreateFile();
    if (hIcmpFile == INVALID_HANDLE_VALUE) {
      Result = false;
      return Result;
    }
    ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData);
    ReplyBuffer = (VOID*) malloc(ReplySize);
    if (ReplyBuffer == NULL) {
      Result = false;  // No localizacion de memoria...
      return Result;
    }

    // Envia Ping
    Result = true;
    for(int n=0; n<NVeces>ProcessMessages();
      dwRetVal = IcmpSendEcho(hIcmpFile, ipaddr, SendData, sizeof(SendData),
          NULL, ReplyBuffer, ReplySize, 1000);

      if (dwRetVal != 0) {
        PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;
        // Detectar Error en Ping (IP_STATUS)
        // ICMP_ECHO_REPLY Structure IP_STATUS code
        // http://msdn2.microsoft.com/en-us/library/aa366053(VS.85).aspx
        if(pEchoReply->Status != 0){
            Result = false;  // Error en Ping el Host no lo recibe....
        }
      }else{
        Result = false;  // Error en IcmpSendEcho localizar con GetLastError()
      }
      if(Result) break;
      Sleep(1000);
    }

    free(ReplyBuffer);
    return Result;
}

Saludos.

wildnetboy 15-05-2008 07:45:57

Hola no se si soy muy tonto o que pasa pero nologro hecharlo a andar no se que pase a ver si me hechas un cable...
gracias

escafandra 20-05-2008 20:57:38

Bien. ¿Puedes especificar mejor el problema? ¿Donde te surge el error?.
Saludos.

escafandra 21-05-2008 12:25:59

Bueno, entiendo que pueden existir problemas, para algunos, a la hora de enlazar las funciones de las dll que necesita el truco. Para los que estén en este caso, les recomiendo que repasen el programa IMPLIB. Se trata sede crear librerias tipo.lib de esas dlls y enlazarlas a la aplicación tal cual. Este puede ser una buena forma de comenzar.

Lo siguiente... Es utilizar el código del truco.

Os dejo un ejemplo práctico:
http://<br /> http://www.clubdelphi...Ping.zip<br />

Y como el espacio de los archivos adjuntos es muy limitado, por si tengo que liberarlo os dejo este otro link:

http://<br /> http://rapidshare.com...Ping.rar<br />

escafandra 21-05-2008 15:01:49

Bueno, entiendo que pueden existir problemas, para algunos, a la hora de enlazar las funciones de las dll que necesita el truco. Para los que estén en este caso, les recomiendo que repasen el programa IMPLIB. Se trata sede crear librerias tipo.lib de esas dlls y enlazarlas a la aplicación tal cual. Este puede ser una buena forma de comenzar.

Lo siguiente... Es utilizar el código del truco.

Os dejo un ejemplo práctico:
http://<br /> http://www.clubdelphi...Ping.zip<br />

Y como el espacio de los archivos adjuntos es muy limitado, por si tengo que liberarlo os dejo este otro link:

http://<br /> http://rapidshare.com...Ping.rar<br />

escafandra 21-05-2008 21:15:21

Bueno, entiendo que pueden existir problemas, para algunos, a la hora de enlazar las funciones de las dll que necesita el truco. Para los que estén en este caso, les recomiendo que repasen el programa IMPLIB. Se trata sede crear librerias tipo.lib de esas dlls y enlazarlas a la aplicación tal cual. Este puede ser una buena forma de comenzar.

Lo siguiente... Es utilizar el código del truco.

Os dejo un ejemplo práctico:
http://<br /> http://www.clubdelphi...Ping.zip<br />

Y como el espacio de los archivos adjuntos es muy limitado, por si tengo que liberarlo os dejo este otro link:

http://<br /> http://rapidshare.com...Ping.rar<br />


La franja horaria es GMT +2. Ahora son las 12:43:02.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi