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.