Page 1 of 2

Hacer Ping a un PC, Como ?

Posted: Tue Jan 18, 2011 1:59 pm
by Adolfo
Holas a todos.

Eso... Como puedo hacer un ping() a un Pc para saber si esta funcionando.

NEcesito saber si un Pc o Servidor ( del cual conozco su IP ) esta conectado para decidir si conectarme a el o nop.
Encontre una solucion aqui en el foro del año 2008 y usa una clase propia (twebservice) o algo asi. Pero quisiera saber si hay algo mas "nuevito"

La funcion GetHostByAddress() a veces me retorna ""

Saludos
Adolfo

Re: Hacer Ping a un PC, Como ?

Posted: Tue Jan 18, 2011 3:28 pm
by mchumpitazv
Hola Adolfo

Y su usas un bat desde el cual realizar el ping, el resultado lo puedes direccionar a un txt y evaluarlo; si en el texto no se presenta la frase "Tiempo de espera agotado para esta solicitud" significa que realizo el ping.
El archivo bat reciviria como parametro la ip a evaluar.

Saludos

Martín

Re: Hacer Ping a un PC, Como ?

Posted: Tue Jan 18, 2011 4:05 pm
by Adolfo
Martin

El problema es la velocidad, ya que debo hacer ping a 3 maquinas, y en algunos pc's la velocidad del ping y sus 4 reintentos es muy alta.
Como se hace al inicio del programa, mas de alguna queja voy a recibir.

Gracias


Adolfo

Re: Hacer Ping a un PC, Como ?

Posted: Tue Jan 18, 2011 6:46 pm
by mgsoft
Hola Adolfo:

Prueba así:

Code: Select all

#include "FiveLinux.ch"

function Main()

   MsgInfo( Ping( "192.168.0.22" ) )
   
return nil

#pragma BEGINDUMP   

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <linux/ip.h>
#include <linux/icmp.h>
#include <string.h>
#include <unistd.h>

char dst_addr[20];
char src_addr[20];

static unsigned short in_cksum(unsigned short *, int);
static void parse_argvs(char**, char*, char* );
static void usage();
static char* getip();
static char* toip(char*);

HB_FUNC( PING )
{
   struct iphdr* ip;
   struct iphdr* ip_reply;
   struct icmphdr* icmp;
   struct sockaddr_in connection;
   char* packet;
   char* buffer;
   int sockfd;
   int optval;
   int addrlen;
   int siz;

   /*
   if (getuid() != 0)
   {
       fprintf(stderr, "%s: root privelidges needed\n", *(argv + 0));
       exit(EXIT_FAILURE);
   }
   */

   // parse_argvs(argv, dst_addr, src_addr);
   strncpy( dst_addr, toip( ( char * ) hb_parc( 1 ) ), 20 );
   strncpy( src_addr, toip( getip() ), 20 );
   // printf("Source address: %s\n", src_addr);
   // printf("Destination address: %s\n", dst_addr);

   /*
    * allocate all necessary memory
   */
   packet = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
   buffer = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
   /****************************************************************/

   ip = (struct iphdr*) packet;
   icmp = (struct icmphdr*) (packet + sizeof(struct iphdr));

   /*
    *  here the ip packet is set up
    */
   ip->ihl                     = 5;
   ip->version                 = 4;
   ip->tos                     = 0;
   ip->tot_len                 = sizeof(struct iphdr) + sizeof(struct icmphdr);
   ip->id                      = htons(0);
   ip->frag_off                = 0;
   ip->ttl                     = 64;
   ip->protocol                = IPPROTO_ICMP;
   ip->saddr                   = inet_addr(src_addr);
   ip->daddr                   = inet_addr(dst_addr);
   ip->check                   = in_cksum((unsigned short *)ip, sizeof(struct iphdr));

   if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1)
   {
       hb_retl( FALSE );
       return;
       // perror("socket");
       // exit(EXIT_FAILURE);
   }

   /*
    *  IP_HDRINCL must be set on the socket so that
    *  the kernel does not attempt to automatically add
    *  a default ip header to the packet
    */

   setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(int));

   /*
    *  here the icmp packet is created
    *  also the ip checksum is generated
    */
   icmp->type                  = ICMP_ECHO;
   icmp->code                  = 0;
   icmp->un.echo.id            = random();
   icmp->un.echo.sequence      = 0;
   icmp-> checksum             = in_cksum((unsigned short *)icmp, sizeof(struct icmphdr));


   connection.sin_family = AF_INET;
   connection.sin_addr.s_addr = inet_addr(dst_addr);

   /*
    *  now the packet is sent
    */

   sendto(sockfd, packet, ip->tot_len, 0, (struct sockaddr*)&connection, sizeof(struct sockaddr));
   // printf("Sent %d byte packet to %s\n", ip->tot_len, dst_addr);

   /*
    *  now we listen for responses
    */
   addrlen = sizeof(connection);
   if (( siz = recvfrom(sockfd, buffer, sizeof(struct iphdr) + sizeof(struct icmphdr), 0, (struct sockaddr *)&connection, &addrlen)) == -1)
   {
       hb_retl( FALSE );
       // perror("recv");
   }
   else
   {
       hb_retl( TRUE );
       // printf("Received %d byte reply from %s:\n", siz , dst_addr);
       // ip_reply = (struct iphdr*) buffer;
       // printf("ID: %d\n", ntohs(ip_reply->id));
       // printf("TTL: %d\n", ip_reply->ttl);
   }

   free(packet);
   free(buffer);
   close(sockfd);
   // return 0;
}

static void parse_argvs(char** argv, char* dst, char* src)
{
   int i;
   if(!(*(argv + 1)))
   {
       /* there are no options on the command line */
       usage();
       exit(EXIT_FAILURE);
   }
   if (*(argv + 1) && (!(*(argv + 2))))
   {
       /*
        *   only one argument provided
        *   assume it is the destination server
        *   source address is local host
        */
       strncpy(dst, *(argv + 1), 15);
       strncpy(src, getip(), 15);
       return;
   }
   else if ((*(argv + 1) && (*(argv + 2))))
   {
       /*
        *    both the destination and source address are defined
        *    for now only implemented is a source address and
        *    destination address
        */
       strncpy(dst, *(argv + 1), 15);
       i = 2;
       while(*(argv + i + 1))
       {
           if (strncmp(*(argv + i), "-s", 2) == 0)
           {
               strncpy(src, *(argv + i + 1), 15);
               break;
           }
           i++;
       }
   }

}

static void usage()
{
   fprintf(stderr, "\nUsage: pinger [destination] <-s [source]>\n");
   fprintf(stderr, "Destination must be provided\n");
   fprintf(stderr, "Source is optional\n\n");
}

static char* getip()
{
   char buffer[256];
   struct hostent* h;

   gethostname(buffer, 256);
   h = gethostbyname(buffer);

   return inet_ntoa(*(struct in_addr *)h->h_addr);

}

/*
 * return the ip address if host provided by DNS name
 */
static char* toip(char* address)
{
   struct hostent* h;
   h = gethostbyname(address);
   return inet_ntoa(*(struct in_addr *)h->h_addr);
}

/*
 * in_cksum --
 * Checksum routine for Internet Protocol
 * family headers (C Version)
 */
static unsigned short in_cksum(unsigned short *addr, int len)
{
   register int sum = 0;
   u_short answer = 0;
   register u_short *w = addr;
   register int nleft = len;
   /*
    * Our algorithm is simple, using a 32 bit accumulator (sum), we add
    * sequential 16 bit words to it, and at the end, fold back all the
    * carry bits from the top 16 bits into the lower 16 bits.
    */
   while (nleft > 1)
   {
         sum += *w++;
         nleft -= 2;
   }
   /* mop up an odd byte, if necessary */
   if (nleft == 1)
   {
         *(u_char *) (&answer) = *(u_char *) w;
         sum += answer;
   }
   /* add back carry outs from top 16 bits to low 16 bits */
   sum = (sum >> 16) + (sum & 0xffff);         /* add hi 16 to low 16 */
   sum += (sum >> 16);                         /* add carry */
   answer = ~sum;                              /* truncate to 16 bits */
   return (answer);
}

#pragma ENDDUMP
 

Re: Hacer Ping a un PC, Como ?

Posted: Tue Jan 18, 2011 8:09 pm
by Adolfo
MGSOFT..

Habia visto ese post, pero la solucion es para FIVELINUX, de hecho se incluyen archivos de cabecera que no poseo.

Gracias

Re: Hacer Ping a un PC, Como ?

Posted: Tue Jan 18, 2011 8:12 pm
by jrestojeda
Adolfo...
Recuerda que el Ping tiene el parámetro -n que sirve para decir que cantidad de intentos quiero hacer.

PING 192.168.1.40 -n 1

Sólo enviará un solo paquete.
Espero sirva de ayuda.
Saludos,

Re: Hacer Ping a un PC, Como ?

Posted: Tue Jan 18, 2011 8:28 pm
by Adolfo
jrestojeda....

Sip, ya habia caido en eso... al momento parece ser la solucion, ( no la mas esperada, pero creo que funcionara )

A propo, de las funciones de manejo de internet y sockets de xharbour, como no habra por ahi un pedazo de codigo en C que haga la pega... mm voy a bajarme los sources y vere si "adivino" donde estara la solucion... trabajo para la casa.


Saludos.

si alguien encuentra por ahi algo.. envie la solucion sin problemas.

Adolfo

Re: Hacer Ping a un PC, Como ?

Posted: Wed Jan 19, 2011 12:30 am
by jrestojeda
Adolfo...
Una pequeña prueba que estuve haciendo...

Code: Select all

// PRUEBA DE PING //
Function Ping(DestinationAddress)
Local IcmpHandle,Replicas,puerto
Local RequestData   :="Probando ping",;
      RequestSize   :=15,;
      RequestOptions:="",;
      ReplyBuffer   :=SPACE(278),;
      ReplySize     :=278,;
      Timeout       :=500 && Milisegundos de espera

DEFAULT DestinationAddress := "127.0.0.1"

DestinationAddress:=LEFT(ALLTRIM(DestinationAddress)+SPACE(15),15)

MsgGet("Ping...","Ingrese una dirección IP",@DestinationAddress)

IcmpHandle:=IcmpCreateFile()
Replicas  :=IcmpSendEcho(IcmpHandle,;
                          inet_addr(DestinationAddress),;
                          RequestData,;
                          RequestSize,0,;
                          ReplyBuffer,;
                          ReplySize,;
                          Timeout)

IcmpCloseHandle(IcmpHandle)

IF Replicas > 0
   Msginfo("Respuesta correcta del host "+ALLTRIM(DestinationAddress),"Atención")
ELSE
   Msginfo("Host inaccesible"+ALLTRIM(DestinationAddress)+"Atención")
ENDIF

Return nil
//

DLL32 FUNCTION WSAGetLastError() AS _INT PASCAL FROM "WSAGetLastError" LIB "wsock32.dll"
DLL32 FUNCTION inet_addr(cIP AS STRING) AS LONG PASCAL FROM "inet_addr" LIB "wsock32.dll"
DLL32 FUNCTION IcmpCreateFile() AS LONG PASCAL FROM "IcmpCreateFile" LIB "icmp.dll"
DLL32 FUNCTION IcmpCloseHandle(IcmpHandle AS LONG) AS LONG PASCAL FROM "IcmpCloseHandle" LIB "icmp.dll"
DLL32 FUNCTION IcmpSendEcho(IcmpHandle AS LONG,;
                            DestinationAddress AS LONG,;
                            RequestData AS STRING,;
                            RequestSize AS LONG,;
                            RequestOptions AS LONG,;
                            ReplyBuffer AS LPSTR,;
                            ReplySize AS LONG,;
                            Timeout AS LONG) AS LONG PASCAL FROM "IcmpSendEcho" LIB "icmp.dll"
 

Re: Hacer Ping a un PC, Como ?

Posted: Wed Jan 19, 2011 12:03 pm
by Daniel Garcia-Gil
Esteban

Gracias por el ejemplo, me generaba un error si no inicializaba WinSock aparte tuve que ampliarle el timeout a 1000

Code: Select all

   if WSAStartup() != 0
       MsgAlert( "WSAStartup error" )
       return nil
   endif
publico un ejemplo funcional usando la funcion de esteban y el equivalente desde C
valores de retorno de hb_ping
0 = Conexion exitosa
1 = IP invalida
2 = No pudo crear el paquete de envio
3 = No pudo crear el buffer de replica
4 = No hay conexion con el host

Code: Select all

#include "fivewin.ch"

// PRUEBA DE PING //

function main()

   if WSAStartup() != 0
       MsgAlert( "WSAStartup error" )
       return nil
   endif
     
   if hb_Ping( GetHostByName( "www.google.com" ) ) == 0
      Msginfo("Respuesta correcta del host " + AllTrim( GetHostByName( "www.google.com" ) ), "Atención" )
   else
      Msginfo("Host inaccesible" + AllTrim( GetHostByName( "www.google.com" ) ), "Atención" )
   endif
  
   Ping( GetHostByName( "www.google.com" ) )
   
   WSACleanUp()

   
return nil


Function Ping(DestinationAddress)
Local IcmpHandle,Replicas,puerto
Local RequestData   :="Probando ping",;
      RequestSize   :=15,;
      RequestOptions:="",;
      ReplyBuffer   :=SPACE(278),;
      ReplySize     :=278,;
      Timeout       := 1000 && Milisegundos de espera

DEFAULT DestinationAddress := "127.0.0.1"

DestinationAddress:=LEFT(ALLTRIM(DestinationAddress)+SPACE(15),15)

MsgGet("Ping...","Ingrese una dirección IP",@DestinationAddress)

IcmpHandle:=IcmpCreateFile()

Replicas  :=IcmpSendEcho(IcmpHandle,;
                          inet_addr(DestinationAddress),;
                          RequestData,;
                          RequestSize,0,;
                          ReplyBuffer,;
                          ReplySize,;
                          Timeout)

IcmpCloseHandle(IcmpHandle)

IF Replicas > 0
   Msginfo("Respuesta correcta del host "+ALLTRIM(DestinationAddress),"Atención")
ELSE
   Msginfo("Host inaccesible"+ALLTRIM(DestinationAddress)+"Atención")
ENDIF

Return nil
//

DLL32 FUNCTION WSAGetLastError() AS _INT PASCAL FROM "WSAGetLastError" LIB "wsock32.dll"
DLL32 FUNCTION inet_addr(cIP AS STRING) AS LONG PASCAL FROM "inet_addr" LIB "wsock32.dll"
DLL32 FUNCTION IcmpCreateFile() AS LONG PASCAL FROM "IcmpCreateFile" LIB "icmp.dll"
DLL32 FUNCTION IcmpCloseHandle(IcmpHandle AS LONG) AS LONG PASCAL FROM "IcmpCloseHandle" LIB "icmp.dll"
DLL32 FUNCTION IcmpSendEcho(IcmpHandle AS LONG,;
                            DestinationAddress AS LONG,;
                            RequestData AS STRING,;
                            RequestSize AS LONG,;
                            RequestOptions AS LONG,;
                            ReplyBuffer AS LPSTR,;
                            ReplySize AS LONG,;
                            Timeout AS LONG) AS LONG PASCAL FROM "IcmpSendEcho" LIB "icmp.dll"

#pragma BEGINDUMP
#include <hbapi.h> 
#include <winsock2.h>
#include <iphlpapi.h>
#include <icmpapi.h>

int hb_Ping( const char * cp )
{
    HANDLE hIcmpFile;
    unsigned long ipaddr;
    DWORD dwRetVal;
    char SendData[32] = "Data Buffer";
    LPVOID ReplyBuffer;
    DWORD ReplySize;

    ipaddr = inet_addr( cp );
    if (ipaddr == INADDR_NONE)
        return 1;
    
    hIcmpFile = IcmpCreateFile();
    if (hIcmpFile == INVALID_HANDLE_VALUE)
        return 2;

    ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData);
    ReplyBuffer = (VOID*) malloc(ReplySize);
    if (ReplyBuffer == NULL)
        return 3;
    
    
    dwRetVal = IcmpSendEcho(hIcmpFile, ipaddr, SendData, sizeof(SendData), 
        NULL, ReplyBuffer, ReplySize, 1000);

    if (dwRetVal == 0)
        return 4;
    
    return 0;

}


HB_FUNC( HB_PING )
{
   hb_retni( hb_Ping( hb_parc( 1 ) ) );
}

#pragma ENDDUMP
 

Re: Hacer Ping a un PC, Como ?

Posted: Wed Jan 19, 2011 1:29 pm
by Adolfo
Ya habia probado con el Bat y las velocidad de prueba es normal.

Pruebo con esta funcion y comento..

Gracias a Todos

Desde Chile
Adolfo

Re: Hacer Ping a un PC, Como ?

Posted: Wed Jan 19, 2011 2:00 pm
by Adolfo
Tengo 2 errores.

Unresolved external : IcmpCreateFile()
Unresolved external : IcmpSendEcho()


Recuerden que utilizo xHarbour for BCC5.8.2 1.2.1 Rev 6741

PD: En Windows 7 Ultimate

Saludos
Adolfo

Re: Hacer Ping a un PC, Como ?

Posted: Wed Jan 19, 2011 2:06 pm
by Daniel Garcia-Gil
Adolfo...

te falta enlazar iphlpapi.lib de borland

Re: Hacer Ping a un PC, Como ?

Posted: Wed Jan 19, 2011 2:23 pm
by Adolfo
Daniel... upsss tienes razon

Grax

Funciona de maravillas y mas rapido que usando el Bat.

Consulto 3 Ip's en menos de 3 segundos

Gracias a Todos

Re: Hacer Ping a un PC, Como ?

Posted: Wed Jan 19, 2011 2:47 pm
by jrestojeda
Hola...
Daniel, que bueno que la función sirvió como punto de partida. A propósito, te comento que yo con Windows XP con el TimeOut de 500 milisegundos no tengo problemas. Quizas sea porque sólo hice pruebas en LAN.

Adolfo, que bueno que lo solucionaste.

Saludos a ambos.

Re: Hacer Ping a un PC, Como ?

Posted: Mon Jul 01, 2013 6:30 am
by Manuel Valdenebro
Añadir que para Windows-7 es necesario hacer un Loadlib32("iphlpapi.dll"). En caso contrario, se cuelga.