Jump to content


Photo

Ping sin componentes


  • Please log in to reply
2 replies to this topic

#1 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 14 April 2009 - 01:59 PM

Como respuesta a una pregunta del foro y por no sobrecargar de C una pregunta hecha para delphi, publico aquí­ un ejemplo de como hacer un Ping desde código usando sólo la API. El parámetro recibido como IP debe ser eso, una dirección IP. Admite reperir el Ping n veces y devuelve el resultado como bool:
 


cpp
  1. #pragma link "$(BCB)\\lib\\PSDK\\Wininet.lib"
  2. #pragma link "icmp.lib"
  3.  
  4. #include <winsock2.h>
  5. #include <iphlpapi.h>
  6. #include "icmpapi.h"
  7.  
  8.  
  9. //---------------------------------------------------------------------------
  10. //  Hacer Ping y conocer el resultado
  11. //  Entrada IP en formato 255.255.255.255
  12. //  Devuelve true si tiene exito o false si hubo un error.
  13. //------------------------------------------------------------------------------
  14. bool Ping(char* Addr, int NVeces)
  15. {
  16.     //Formato de Addr NNN.NNN.NNN.NNN
  17.  
  18.     //Declarar e inicializar variables
  19.     bool Result = true;
  20.     HANDLE hIcmpFile;
  21.     unsigned long ipaddr = INADDR_NONE;
  22.     DWORD dwRetVal = 0;
  23.     char SendData[] = "Data Buffer";
  24.     LPVOID ReplyBuffer = NULL;
  25.     DWORD ReplySize = 0;
  26.  
  27.     //Obtener IP de Addr
  28.     ipaddr = inet_addr(Addr);
  29.     if (ipaddr == INADDR_NONE){
  30.       Result = false;
  31.       return Result;
  32.     }
  33.  
  34.     hIcmpFile = IcmpCreateFile();
  35.     if (hIcmpFile == INVALID_HANDLE_VALUE) {
  36.       Result = false;
  37.       return Result;
  38.     }
  39.     ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData) + 64;
  40.     ReplyBuffer = (VOID*) malloc(ReplySize);
  41.     if (ReplyBuffer == NULL) {
  42.       Result = false;  // No localizacion de memoria...
  43.       return Result;
  44.     }
  45.  
  46.     // Envia Ping
  47.     Result = true;
  48.     for(int n=0; n<NVeces; n++){
  49.       Application->ProcessMessages();
  50.       dwRetVal = IcmpSendEcho(hIcmpFile, ipaddr, SendData, sizeof(SendData),
  51.           NULL, ReplyBuffer, ReplySize, 1000);
  52.  
  53.       if (dwRetVal != 0) {
  54.         PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;
  55.         // Detectar Error en Ping (IP_STATUS)
  56.         // ICMP_ECHO_REPLY Structure IP_STATUS code
  57.         // [url]http://msdn2.microsoft.com/en-us/library/aa366053(VS.85).aspx[/url]
  58.         if(pEchoReply->Status != 0){
  59.             Result = false;  // Error en Ping el Host no lo recibe....
  60.         }
  61.       }else{
  62.         Result = false;  // Error en IcmpSendEcho localizar con GetLastError()
  63.       }
  64.       if(Result) break;
  65.       Sleep(1000);
  66.     }
  67.  
  68.     free(ReplyBuffer);
  69.     return Result;
  70. }

Saludos.

PD. Me olvidaba comentar que icmp.lib es la librerí­a obtenida con IMPLIB de icmp.dll. También debemos enlazar Wininet.lib (de Wininet.dll)

Así­ mismo, el archivo cabecera icmpapi.h no viene en alguna versión de Builder, los dejo aquí­.

Subo todo el código y un ejemplo con fuentes y compilado.

Attached Files


  • 0

#2 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 05 August 2009 - 04:36 PM

Esta función Ping me ha dado muy buenos resultados durante mucho tiempo. La he usado, principalmente, para detectar que tengo conexión en Internet, para ello hago un Ping a www.google.com.

Después de mucho tiempo disfrutando de esta función me ha empezado a fallar. He comprobado que ahora falla con algunas webs (google.com, microsoft.com) y no con otras (delphiacces.com)

Así­ las cosas no he tenido mas remedio que revisar el fallo. Lo que me despistó es porqué falla ahora cuando antes no lo hací­a y además es fallo es intermitente. Pensé en algún cambio de alguna dll de las usadas por las APIs (IcmpSendEcho).

Lo he solucionado aumentando el tamaño del buffer de respuesta ReplyBuffer. Ahora vuelve a funcionar como antes. :D

En el primer mensaje, he editado el código con la corrección:



cpp
  1. ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData) + 64;



También he añadido una aplicación de ejemplo, disponible como descarga.

Saludos.
  • 0

#3 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 07 September 2011 - 04:00 AM

Tras contestar a mediazg en este hilo propongo otra versión del código que incorpora el ping a URLs e IPs:


cpp
  1. bool Ping(char* Addr, int NVeces = 3)
  2. {
  3.   //Declarar e inicializar variables
  4.   WSADATA wsaData;
  5.   HANDLE hIcmpFile;
  6.   ICMP_ECHO_REPLY Reply;
  7.   hostent* He;
  8.   bool Result = false;
  9.  
  10.   // Inicializar WinSock
  11.   if(WSAStartup(MAKEWORD(1, 1), &wsaData)) return false;
  12.  
  13.   //Obtener IP de Addr
  14.   He = gethostbyname(Addr);
  15.   if(!He) return false;
  16.  
  17.   // Envia Ping
  18.   hIcmpFile = IcmpCreateFile();
  19.   for(int n=0; n<NVeces; n++){
  20.     Application->ProcessMessages();
  21.     Result = IcmpSendEcho(hIcmpFile, *(unsigned long*)(*He->h_addr_list), 0, 0, 0, &Reply, sizeof(ICMP_ECHO_REPLY), 1000);
  22.     if(Result)
  23.       Result = (Reply.Status == 0); // Error en Ping el Host no lo recibe....
  24.     else break;
  25.     Sleep(1000);
  26.   }
  27.  
  28.   // Cerrar...
  29.   IcmpCloseHandle(hIcmpFile);
  30.   WSACleanup();
  31.  
  32.   return Result;
  33. }



Y en delphi:

delphi
  1. function Ping(Addr: PCHAR; Rep: integer = 3): boolean;
  2. var
  3.   WSA: TWSAData;
  4.   hIcmpFile: Cardinal;
  5.   Reply: ICMP_ECHO_REPLY;
  6.   He: Phostent;
  7. begin
  8.   Result:= false;
  9.  
  10.   // Inicializar WinSock
  11.   if WSAStartup(MAKEWORD(1, 1), WSA) <> 0 then exit;
  12.  
  13.   //Obtener IP de Addr
  14.   He:= gethostbyname(Addr);
  15.   if He = nil then exit;
  16.  
  17.   // Envia Ping
  18.   hIcmpFile:= IcmpCreateFile;
  19.   repeat
  20.     Result:= IcmpSendEcho(hIcmpFile, PULONG(He.h_addr_list^)^, 0, 0, 0, PCHAR(@Reply), sizeof(ICMP_ECHO_REPLY), 1000) <> 0;
  21.     if Result then
  22.       Result:= Reply.Status = 0; // Error en Ping el Host no lo recibe....
  23.     dec(Rep);
  24.     Sleep(1000);
  25.   until Result or (Rep = 0);
  26.  
  27.   // Cerrar...
  28.   IcmpCloseHandle(hIcmpFile);
  29.   WSACleanup;
  30. end;


Saludos.
  • 0




IP.Board spam blocked by CleanTalk.