Añadida a la sección Descargas la aplicación AjpdSoft Ping ICMP: realiza un ping (comprueba el estado de la conexión con un equipo remoto por medio de los paquetes de solicitud de eco y de respuesta de eco). Permite indicar el tamaño en bytes del paquete a enviar, la IP o el hostname (nombre de red) del equipo remoto (tanto de la LAN como de Internet), el número de intentos de ping que se realizará y el tiempo en milisegundos entre intento. Muestra los resultados en pantalla y permite guardarlos en fichero de texto. Liberamos el código fuente – source code en Borland Delphi 6 100% Open Source.
- Definición de Ping.
- Características más importantes de AjpdSoft Ping ICMP.
- AjpdSoft Ping ICMP en funcionamiento.
- Instalación y configuración de AjpdSoft Ping ICMP.
- Datos técnicos de AjpdSoft Ping ICMP.
- A quién va dirigida AjpdSoft Ping ICMP.
- Anexo.
Definición de Ping
La utilidad de ping comprueba el estado de la conexión con un equipo remoto por medio de los paquetes de solicitud de eco y de respuesta de eco (ambos definidos en el protocolo de red ICMP) para determinar si un sistema IP específico es accesible en una red. Es útil para diagnosticar los errores en redes o enrutadores IP.
Muchas veces se utiliza para medir la latencia o tiempo que tardan en comunicarse dos puntos remotos.
Con el comando ping podemos ver lo «lejos» que está un equipo verificando los TTL (Tiempo de Vida o Time To Live es un concepto usado para indicar por cuántos nodos puede pasar un paquete antes de ser descartado por la red o devuelto a su origen).
El TTL o TimeToLive es utilizado en el paquete IP de manera que los routers puedan analizarlo y actuar según su contenido. Si un router recibe un paquete con un TTL igual a uno o cero, no lo envía a través de sus puertos, sino que notifica vía ICMP a la dirección IP origen que el destino se encuentra «muy alejado». Si un paquete es recibido por un router que no es el destino, éste decrementa el valor del TTL en uno y envía el paquete al siguiente router (next hop).
En el protocolo IP, esta información se almacena en un campo de 8 bits. El valor óptimo para aprovechar el rendimiento en Internet del TTL es de 128.
Características más importantes de AjpdSoft Ping ICMP
- Aplicación de muy sencillo manejo, muy fácil e intuitiva, todas las opciones están en una misma ventana.
- La aplicación ha sido desarrollada en el lenguaje de programación Borland Delphi 6.
- No necesita instalación, es suficiente con ejecutar el fichero pingICMP.exe.
- Admite parámetros, pasándole como parámetro la IP o el hostname del equipo remoto.
- Permite especificar el tamaño en bytes del paquete a enviar.
- Permite indicar el número de repeticiones del ping que se realizará.
- Permite personalizar el tiempo entre repetición en milisegundos.
- Se puede guardar el resultado del ping en un fichero de texto.
- Guarda automáticamente los equipos a los que se les haya hecho ping en una lista desplegable.
AjpdSoft Ping ICMP en funcionamiento
AjpdSoft Ping ICMP realiza un ping a un equipo de nuestra LAN o de Internet. Para ello será suficiente con abrir el fichero pingICMP.exe e introducir en «IP/Hostname» la dirección IP o el nombre de red (hostname) del equipo al que queramos realizarle el ping. A continuación pulsaremos en «Ping» y la aplicación nos irá mostrando el resultado de los intentos de ping que vaya realizando:
Podremos personalizar las siguientes opciones:
- Bytes: número de bytes que se enviarán en el paquete del ping (por defecto 32).
- Tiempo: número de milisegundos entre cada paquete enviado (por defecto 1000).
- Nº paquetes: número de intentos de ping que se realizarán (número de paquetes que se enviarán).
La aplicación, una vez que haya finalizado el número de paquetes a enviar para el ping, mostrará un resultado como este:
05/05/2010 13:12:52 Realizando ping a proyectoa.com [OK]
05/05/2010 13:12:52 Realizando ping proyectoa.com [82.98.144.32]
05/05/2010 13:12:52 Respuesta desde 82.98.144.32: bytes = 32 tiempo=16ms TTL=53
05/05/2010 13:12:53 Respuesta desde 82.98.144.32: bytes = 32 tiempo=17ms TTL=53
05/05/2010 13:12:54 Respuesta desde 82.98.144.32: bytes = 32 tiempo=16ms TTL=53
Estadísticas de ping para 82.98.144.32:
Paquetes:
+ Enviados = 3
+ Recibidos = 3
+ Perdidos = 0
Tiempos aproximados de envío y recepción:
+ Mínimo = 16 ms
+ Máximo = 17 ms
+ Media = 16ms
Podremos guardar estos datos pulsando en el botón «Guardar»:
Indicaremos la carpeta y el nombre del fichero a guardar:
Instalación y configuración de AjpdSoft Ping ICMP
AjpdSoft Ping ICMP no necesita instalación, se puede ejecutar directamente el fichero pingICMP.exe. La aplicación necesitará la librería icmp.dll que viene con Windows por defecto.
Datos técnicos de AjpdSoft Ping ICMP
Esta aplicación ha sido desarrollada en el lenguaje de programación Borland Delphi 6. La aplicación utiliza la función del API de Windows IcmpSendEcho, por lo que requiere de la librería icmp.dll que viene por defecto con Windows.
Si eres desarrollador de software y te has registrado en nuestra web (si aún no te has registrado puedes hacerlo desde aquí gratuitamente) puedes descargar el código fuente 100% Open Source (completo y totalmente gratuito) en Borland Delphi 6:
AjpdSoft Ping ICMP ha sido testada y funciona correctamente en equipos con sistemas operativos: Windows XP, Windows 2000 Server, Windows Server 2003, Windows Vista y Windows 7 (Seven).
Para usuarios desarrolladores de software
La aplicación utiliza los siguientes componentes (para Delphi 6):
- Windows XP Theme Manager 1.10.1: adaptar la aplicación al tema visual de Windows (gratuito – freeware).
A quién va dirigida AjpdSoft Ping ICMP
La aplicación AjpdSoft Ping ICMP va dirigida a administradores de sistemas, administradores de red y usuarios que quieran realizar ping de forma más efectiva que utilizando el comando ping de Windows. Esta aplicación utiliza el mismo procedimiento pero permite modificar algunos parámetros.
También puede ser útil para estudiantes que tengan que realizar algún proyecto de ejemplo de desarrollo de aplicación que realice un ping.
Anexo
Unidad «UnidadMenuPrincipal.pas»:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
unit UnidadMenuPrincipal; {$R WinXP.res} interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, aping, ComCtrls, shellapi, Buttons, ThemeMgr, inifiles; type TformMenuPrincipal = class(TForm) txtResultado: TMemo; LWEB: TLabel; bGuardar: TBitBtn; ThemeManager1: TThemeManager; dlGuardar: TSaveDialog; bSalir: TBitBtn; GroupBox1: TGroupBox; Label1: TLabel; Label2: TLabel; Label3: TLabel; txtIP: TComboBox; txtBytes: TEdit; txtTiempo: TEdit; txtNumRepeticiones: TEdit; Label4: TLabel; btPing: TBitBtn; opLimpiar: TCheckBox; procedure btPingClick(Sender: TObject); procedure txtIPKeyPress(Sender: TObject; var Key: Char); procedure LWEBClick(Sender: TObject); procedure bGuardarClick(Sender: TObject); procedure bSalirClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; type ip_option_information = record Ttl : byte; Tos : byte; Flags : byte; OptionsSize : byte; OptionsData : pointer; end; ICMP_ECHO_REPLY = record Address : IPAddr; Status : ULONG; RoundTripTime : ULONG; DataSize : Word; Reserved : Word; Data : Pointer; Options : IP_OPTION_INFORMATION; end; var formMenuPrincipal: TformMenuPrincipal; implementation {$R *.dfm} function buscarElementoComboBox ( combo : TComboBox; elemento : string) : boolean; var i : integer; begin Result := false; for i := 0 to combo.Items.Count - 1 do begin if AnsiUpperCase(combo.Items[i]) = AnsiUpperCase(elemento) then begin Result := true; Exit; end; end; end; //lee un valor booleano de un fichero INI function leBoolINI (clave, cadena : string; defecto : boolean) : boolean; begin with tinifile.create (changefileext(paramstr(0),'.INI')) do try result := readbool (clave, cadena, defecto); finally free; end; end; //lee un valor numérico de un fichero INI function leNumINI (clave, cadena : string; defecto : Integer) : Integer; begin with tinifile.create (changefileext(paramstr(0),'.INI')) do try result := ReadInteger (clave, cadena, defecto); finally free; end; end; //lee un valor string de un fichero INI function leCadINI (clave, cadena : string; defecto : String) : String; begin with tinifile.create (changefileext(paramstr(0),'.INI')) do try result := ReadString (clave, cadena, defecto); finally free; end; end; //escribe un valor string en un fichero INI procedure esCadINI (clave, cadena : string; valor : String); begin with tinifile.create (changefileext(paramstr(0),'.INI')) do try WriteString (clave, cadena, valor); finally free; end; end; //escribe un valor boolean en un fichero INI procedure esBoolINI (clave, cadena : string; valor : Boolean); begin with tinifile.create (changefileext(paramstr(0),'.INI')) do try WriteBool (clave, cadena, valor); finally free; end; end; procedure TformMenuPrincipal.btPingClick(Sender: TObject); var Handle : THandle; InAddr : IPAddr; DW : DWORD; cnt : integer; SAddr : string; pnum : integer; minTime : longint; maxTime : longint; allTime : longint; stat : longint; PingBuf : array[0..31] of char; Reply : ICMP_ECHO_REPLY; begin if opLimpiar.Checked then begin txtResultado.Clear; Refresh; end; if txtResultado.Text <> '' then begin txtResultado.Lines.Add(''); txtResultado.Lines.Add(''); end; if ping(txtIP.Text) then begin txtResultado.Lines.Add (DateTimeToStr(Now) + ' ' + 'Realizando ping a ' + txtIP.Text + ' [OK]'); if not buscarElementoComboBox(txtIP, txtIP.Text) then txtIP.Items.Add (txtIP.Text); txtIP.Items.SaveToFile( IncludeTrailingPathDelimiter (ExtractFilePath(Application.ExeName)) + 'equipos.txt'); end else txtResultado.Lines.Add (DateTimeToStr(Now) + ' Realizando ping a ' + txtIP.Text + ' [NO DISPONIBLE]'); Handle := IcmpCreateFile; if Handle = INVALID_HANDLE_VALUE then Halt(2); TranslateStringToTInAddr(txtIP.Text, InAddr); SAddr := Format('%d.%d.%d.%d',[InAddr.S_un_b.s_b1, InAddr.S_un_b.s_b2, InAddr.S_un_b.s_b3, InAddr.S_un_b.s_b4]); txtResultado.Lines.Add (DateTimeToStr(Now) + Format (' Realizando ping %s [%s]',[txtIP.Text, SAddr]) ); pnum := 0; minTime := MaxInt -1; maxTime := 0; AllTime := 0; Reply.Data := @pingBuf; Reply.DataSize := 32; for cnt := 1 to StrToInt(txtNumRepeticiones.Text) do begin DW := IcmpSendEcho(Handle, InAddr, @PingBuf, strtoint(txtBytes.text), nil, @reply, SizeOf(icmp_echo_reply) + strtoint(txtBytes.text), 3000); if DW = 0 then txtResultado.Lines.Add (DateTimeToStr(Now) + ' Tiempo de espera agotado') else begin txtResultado.Lines.Add (DateTimeToStr(Now) + (Format(' Respuesta desde %s: bytes = ' + txtBytes.Text + ' tiempo=%dms TTL=%d', [SAddr, Reply.RoundTripTime, Reply.Options.Ttl]))); stat := Reply.RoundTripTime; inc(pnum); if minTime > stat then minTime := stat; if maxTime < stat then maxTime := stat; AllTime := AllTime + stat; end; Sleep(StrToInt(txtTiempo.Text)); end; IcmpCloseHandle(Handle); txtResultado.Lines.Add (' Estadísticas de ping para ' + SAddr + ':'); txtResultado.Lines.Add (' Paquetes: '); txtResultado.Lines.Add (' + Enviados = ' + txtNumRepeticiones.Text); txtResultado.Lines.Add (' + Recibidos = ' + inttostr(pnum)); txtResultado.Lines.Add (' + Perdidos = ' + inttostr(strtoint(txtNumRepeticiones.Text) - pnum)); if StrToInt(txtNumRepeticiones.Text) = pnum then begin txtResultado.Lines.Add (' Tiempos aproximados de envío y recepción:'); txtResultado.Lines.Add (' + Mínimo = ' + inttostr(minTime) + ' ms'); txtResultado.Lines.Add (' + Máximo = ' + inttostr(maxTime) + ' ms'); txtResultado.Lines.Add (' + Media = ' + inttostr(round(AllTime / pnum)) + 'ms'); end; end; procedure TformMenuPrincipal.txtIPKeyPress( Sender: TObject; var Key: Char); begin if key = #13 then btPingClick(Self); end; procedure TformMenuPrincipal.LWEBClick(Sender: TObject); begin ShellExecute(Handle, Nil, PChar('https://www.proyectoa.com'), Nil, Nil, SW_SHOWNORMAL); end; procedure TformMenuPrincipal.bGuardarClick(Sender: TObject); begin if dlGuardar.Execute then txtResultado.Lines.SaveToFile(dlGuardar.FileName); end; procedure TformMenuPrincipal.bSalirClick(Sender: TObject); begin close; end; procedure TformMenuPrincipal.FormShow(Sender: TObject); begin if ParamStr(1) <> '' then begin txtIP.Text := ParamStr(1); btPing.SetFocus; end; end; procedure TformMenuPrincipal.FormClose(Sender: TObject; var Action: TCloseAction); begin esCadINI('Datos', 'Equipo', txtIP.Text); esCadINI('Datos', 'Bytes', txtBytes.Text); esCadINI('Datos', 'Tiempo', txtTiempo.Text); esCadINI('Datos', 'Número paquetes', txtNumRepeticiones.Text); esBoolINI('Datos', 'Limpiar datos actuales', opLimpiar.Checked); end; procedure TformMenuPrincipal.FormCreate(Sender: TObject); var fichero : string; begin txtIP.Text := leCadINI('Datos', 'Equipo', 'localhost'); txtBytes.Text := leCadINI('Datos', 'Bytes', '32'); txtTiempo.Text := leCadINI('Datos', 'Tiempo', '1000'); txtNumRepeticiones.Text := leCadINI('Datos', 'Número paquetes', '5'); opLimpiar.Checked := leBoolINI('Datos', 'Limpiar datos actuales', false); fichero := IncludeTrailingPathDelimiter ( ExtractFilePath(Application.ExeName)) + 'equipos.txt'; if FileExists(fichero) then txtIP.Items.LoadFromFile(fichero); end; end. |
Unidad «aping.pas»:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
unit aping; interface uses Windows, SysUtils, Classes; type TSunB = packed record s_b1, s_b2, s_b3, s_b4: byte; end; TSunW = packed record s_w1, s_w2: word; end; PIPAddr = ^TIPAddr; TIPAddr = record case integer of 0: (S_un_b: TSunB); 1: (S_un_w: TSunW); 2: (S_addr: longword); end; IPAddr = TIPAddr; function IcmpCreateFile : THandle; stdcall; external 'icmp.dll'; function IcmpCloseHandle (icmpHandle : THandle) : boolean; stdcall; external 'icmp.dll' function IcmpSendEcho ( IcmpHandle : THandle; DestinationAddress : IPAddr; RequestData : Pointer; RequestSize : Smallint; RequestOptions : pointer; ReplyBuffer : Pointer; ReplySize : DWORD; Timeout : DWORD) : DWORD; stdcall; external 'icmp.dll'; function Ping(InetAddress : string) : boolean; procedure TranslateStringToTInAddr(AIP: string; var AInAddr); implementation uses WinSock; function Fetch(var AInput: string; const ADelim: string = ' '; const ADelete: Boolean = true) : string; var iPos: Integer; begin if ADelim = #0 then begin // AnsiPos does not work with #0 iPos := Pos(ADelim, AInput); end else begin iPos := Pos(ADelim, AInput); end; if iPos = 0 then begin Result := AInput; if ADelete then begin AInput := ''; end; end else begin result := Copy(AInput, 1, iPos - 1); if ADelete then begin Delete(AInput, 1, iPos + Length(ADelim) - 1); end; end; end; procedure TranslateStringToTInAddr(AIP: string; var AInAddr); var phe: PHostEnt; pac: PChar; GInitData: TWSAData; begin WSAStartup($101, GInitData); try phe := GetHostByName(PChar(AIP)); if Assigned(phe) then begin pac := phe^.h_addr_list^; if Assigned(pac) then begin with TIPAddr(AInAddr).S_un_b do begin s_b1 := Byte(pac[0]); s_b2 := Byte(pac[1]); s_b3 := Byte(pac[2]); s_b4 := Byte(pac[3]); end; end else begin raise Exception.Create('Error al obtener la IP del equipo'); end; end else begin raise Exception.Create('Error al obtener el nombre de red'); end; except FillChar(AInAddr, SizeOf(AInAddr), #0); end; WSACleanup; end; function Ping(InetAddress : string) : boolean; var Handle : THandle; InAddr : IPAddr; DW : DWORD; rep : array[1..128] of byte; begin result := false; Handle := IcmpCreateFile; if Handle = INVALID_HANDLE_VALUE then Exit; TranslateStringToTInAddr(InetAddress, InAddr); DW := IcmpSendEcho(Handle, InAddr, nil, 0, nil, @rep, 128, 0); Result := (DW <> 0); IcmpCloseHandle(Handle); end; end.<!-- AddThis Button END --> |