Ir al contenido


Foto

Aplicación se congela al hacer Pings masivo


  • Por favor identifícate para responder
42 respuestas en este tema

#21 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 16 marzo 2009 - 11:00

Hola Kipow y Rolphy, eso ya se habí­a corregido subí­ de nuevo el .pas en el post #17 ;), y aún así­ el problema persiste.

Saludos.
  • 0

#22 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4.483 mensajes
  • LocationVenezuela

Escrito 16 marzo 2009 - 11:02

cual problema persiste?

la lentitud o el error de tipos?
  • 0

#23 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 16 marzo 2009 - 11:06

La lentitud, se congela, cuando hay muchos equipos en TimeOut se congela por un minuto o dos, quisiera que no pareciera que la aplicación esté congelada. :(
  • 0

#24 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4.483 mensajes
  • LocationVenezuela

Escrito 16 marzo 2009 - 11:24

no se que tanto pueda mejorar, pero podrias probrar cambiarle la prioridad...

De esta forma el SO le da toda la prioridad a la ejecucion del hilo.



delphi
  1. constructor TThreadPing.Create(IP: String);
  2. begin
  3.   cIP := IP; //guarda la IP en una variable privada
  4.   inherited Create(True);
  5.   Priority := tpTimeCritical;
  6.   resume;
  7. end;



o de esta forma, no se interrumpe el proceso y el hilo se ejecuta cuando hayan recursos disponibles...



delphi
  1. constructor TThreadPing.Create(IP: String);
  2. begin
  3.   cIP := IP; //guarda la IP en una variable privada
  4.   inherited Create(True);
  5.   Priority := tpIdle;
  6.   resume;
  7. end;



Puedes jugar con los valores de prioridad.

tpIdle
El hilo sólo ejecuta cuando el sistema esta parado. Windows no interrumpirá a otros hilos para ejecutar un hilo con prioridad tpIdle.

tpLowest
La prioridad del hilo está dos puntos por debajo de la normal.

tpLower
La prioridad del hilo está un punto por debajo de la normal.

tpNormal
El hilo tiene una prioridad normal.

tpHigher
La prioridad del hilo está un punto por encima de la normal.

tpHighest
La prioridad del hilo está dos puntos por encima de la normal.

tpTimeCritical 
El hilo tiene la prioridad más alta.



Si quieres leer mas, Aqui
  • 0

#25 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 16 marzo 2009 - 11:59

Hola Fernando, No se si tendrá algo que ver, pero noto que en ningún lado guardas la IP cuando creas el hilo. Lo que si haces es sobreescribir el valor de una variable local (cIP).

¿Porqué el hilo no tiene el atributo o campo para que el mismo sepa hacia donde hacer ping?

Según como lo entiendo, el constructor Create() que definiste cambia el valor de cIP por el pasado por el parámetro. Luego, en el método SetReloj se lee esta variable cIP.

No si es que funciona... pero a mi no me cuadra. Si creo un hilo y paso la IP 1 (es un ejemplo) luego un segundo con una IP 2, y así­ sucesivamente llegarás a que en cIP tengas el valor del último hilo. Ahora bien, el método SetReloj va leyendo cIP y por ello es que algo me late a que siempre leerá el último IP, y no así­ los primeros.

En definitiva... creo que todos los hilos terminan haciendo ping a la misma IP, la última.

Mi consejo: añade un atributo IP y haz que "Recibe.Host" reciba el valor desde éste.

Por otro lado me extraña que no tengas variables del tipo TThreadPing para manejar los hilos... directamente estás creando al vuelo.... ¿es legal estar haciendo TThreadPing.Create()?

No usé hilos nunca pero yo me esperaba algo como:



delphi
  1. Hilo1 := TThreadPing.Create().



El tema del Timer no me cierra. Si ya tenés los hilos ¿para que el timer?
Yo más bien buscarí­a que los propios hilos implementen de forma internan un timming y vuelvan a hacer ping.
Desconozco si es posible hacer ese timming dentro del hilo, pero por allí­ también va la cosa.

Saludos,
  • 0

#26 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4.483 mensajes
  • LocationVenezuela

Escrito 16 marzo 2009 - 12:40

a ver Delphius, trato de llevarte la secuencia:

la duda que tienes de la variable es lo mismo que hacerlo con atributos, el asunto es que siempre se crea una nueva instancia de la clase, y cada una se esta ejecutando por separado, de esta forma la variable nunca se sobreescribiria el valor, cosa que si sucederia si la sacamos del objeto y la declaramos publica en la unit.

Con respecto de crearlos sin asignarlo a una variable no tiene ningun problema, no veo cual seria la diferencia.


NOTA: Estoy hablando en base a experiencia personal, no tengo ninguna documentacion al respecto si alguien puede ilustrarnos al respecto estare muy agradecido, mi formacion con los hilos es auto didacta.

  • 0

#27 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 16 marzo 2009 - 01:24

a ver Delphius, trato de llevarte la secuencia:

la duda que tienes de la variable es lo mismo que hacerlo con atributos, el asunto es que siempre se crea una nueva instancia de la clase, y cada una se esta ejecutando por separado, de esta forma la variable nunca se sobreescribiria el valor, cosa que si sucederia si la sacamos del objeto y la declaramos publica en la unit.

Disculpa si pareciera que llevo la contraria... pero no comprendo. cIP no es privada a la clase, es local (puede accederse a ella desde toda la unit):



delphi
  1. var
  2.   FMain: TFMain;
  3.   Conteo: Integer;
  4.   cIP: String;
  5.  
  6. implementation



Y en la definición de la clase TTHreadPing no está:



delphi
  1. TThreadPing = class(TThread)
  2.   private
  3.     procedure SetReloj;
  4.   protected
  5.     procedure Execute; override;
  6.   public
  7.     Host: String;
  8.     S: TLabel;
  9.     Recibe: TIdIcmpClient;
  10.     G: TJvGIFAnimator;
  11.     constructor Create(IP: String; Destino: TLabel; Imagen: TJvGIFAnimator);
  12.   end;



Lo que noto es que cada vez que se realiza un Create, se está cambiando el valor de cIP:


delphi
  1. constructor TThreadPing.Create(IP: String; Destino: TLabel; Imagen: TJvGIFAnimator);
  2. begin
  3. cIP := IP; //guarda la IP en una variable privada
  4. S := Destino;
  5. G := Imagen;
  6. inherited Create(False);
  7. end;



Por lógica, tras crear 24 hilos, en cIP nos quedamos con el último valor.

Con respecto de crearlos sin asignarlo a una variable no tiene ningun problema, no veo cual seria la diferencia.


NOTA: Estoy hablando en base a experiencia personal, no tengo ninguna documentacion al respecto si alguien puede ilustrarnos al respecto estare muy agradecido, mi formacion con los hilos es auto didacta.

Puede que como dices que no haya problemas. En ocasiones no es necesario tener referencias a los objetos que creamos. Tal vez este sea un caso. Nomás me resulta extraño puesto que por lo que he estado leyendo en la ayuda, y en algunos ejemplos, sobre la clase TTHread, veo que sigue la misma regla que para cualquier objeto:

MiHilo := TMiThread.Create(...)

Lo que no me queda claro es que sucede (por defecto) cuando finaliza... ¿se libera?

Yo no los he puesto en práctica... sólo comento algunas observaciones que me resultaron raras amigo.

Yo me imagino tener 24 hilos creados y mantenerlos (aunque en la ayuda dicen que no es aconsejable tener más de 16). Mandarlos a suspender por tiempo y volverlos a ejecutar. No me parece demasiado viable crear y destruir cada dos pos tres.

Veo que la clase TThread cuenta con los métodos Suspend y Resume... y me parece que están para ello.

¿Porqué no algo como esto?


delphi
  1. Hilo1.Suspend;
  2. Sleep(200);
  3. Hilo2.Resume;



O mejor aún, disponer de un array de hilos y poder trabajar con ellos con un í­ndice. Estuve viendo que existe incluso la clase TThreadList.

No se amigo, reconozco que hablo desde la ignorancia pero dejame comentarte que me siento intrigado.

Saludos,
  • 0

#28 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 16 marzo 2009 - 01:45

Y ahora ando pensando si es bueno tener 24 hilos.... ¿porqué no uno como comentó Domingo? La pregunta que me hago es si es muy adecuado que atienda a todos... ¿"aguantará"?
Los pines toman su "tiempo" por más milisegundos que demoren. Yo me pregunto si será "cómodo" hacer algo como:



delphi
  1. for i := 0 to 23 do
  2.   PingTo(ListIP[i]); 



Habrí­a que hacer la prueba.

Saludos,
  • 0

#29 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4.483 mensajes
  • LocationVenezuela

Escrito 16 marzo 2009 - 01:54

No es llevar la contraria, es ue cuando se tiene razon hay que decirlo...

si, no me habia fijado donde fue a parar el cIp, en mi idea era una variable interna del TThread que recibe el valor por un parametro del create, ahi llevas la razon...

Con respecto a la destruccion no lo habia pensado, y me gusta lo que propones, un solo hilo que haga todos los pines.
  • 0

#30 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 16 marzo 2009 - 02:08

No es llevar la contraria, es ue cuando se tiene razon hay que decirlo...

si, no me habia fijado donde fue a parar el cIp, en mi idea era una variable interna del TThread que recibe el valor por un parametro del create, ahi llevas la razon...

Con respecto a la destruccion no lo habia pensado, y me gusta lo que propones, un solo hilo que haga todos los pines.


Tampoco es para que me dieras el crédito amigo. No creo tener razón, simplemente puse el ojo y NewDelphius se metió a escribir :p

En realidad tanto la idea de hilos como de que uno sólo atienda todo se la merece Domingo, el fue quien comentó el tema, nomás yo vuelvo a poner sobre la mesa de sano debate. :)

Ahorita me voy a merendar, cuando vuelva voy a ver si logro preparar un ejemplo... si alguien ya lo tiene ¡mejor! :D

Saludos,
  • 0

#31 cHackAll

cHackAll

    Advanced Member

  • Administrador
  • 599 mensajes

Escrito 16 marzo 2009 - 02:17

Adjunto otra alternativa que te librará de tener que crear N TLabels y te permitirá hacer que tu interfaz reaccione de acuerdo a la respuesta del ping, trabajando con hilos independientes y mensajes. En el ejemplo, muestro una forma en la que se puede procesar dicha respuesta, sin embargo deberás pulirlo considerando un buffer doble.



delphi
  1. // . . .
  2.  
  3. procedure TForm1.FormCreate(Sender: TObject);
  4. var Index, IP: Integer;
  5. begin
  6. IP := inet_addr('143.1.14.200');
  7. if CloseHandle(IcmpCreateFile) then
  8.   for Index := Low(Reply) to High(Reply) do
  9.   begin
  10.     Reply[Index].Address.S_addr := IP;
  11.     CreateThread(nil, 0, @Thread, Ptr(Index), 0, PDWORD(0)^);
  12.     Inc(PChar(@IP)[3]);
  13.   end;
  14. end;
  15.  
  16. procedure TForm1.PingStatus(var Message: TMessage);
  17. const Colors: array [Boolean] of TColor = (clRed, clBlack);
  18. var
  19. x, y: Cardinal;
  20. Str: string;
  21. begin
  22. x := (Message.WParam mod 3) * 300;
  23. y := (Message.WParam div 3) * 60;
  24. with Reply[Message.WParam] do
  25.   begin
  26.   Canvas.Font.Color := clBlack;
  27.   Canvas.TextOut(x + 50, y, inet_ntoa(Address));
  28.   case Status of
  29.     11000: Str := 'IP_SUCCESS';
  30.     11001: Str := 'IP_BUF_TOO_SMALL';
  31.     11002: Str := 'IP_DEST_NET_UNREACHABLE';
  32.  
  33. // . . .



Salud!

Archivos adjuntos

  • Archivo adjunto  375_.zip   2,02KB   18 descargas

  • 0

#32 cHackAll

cHackAll

    Advanced Member

  • Administrador
  • 599 mensajes

Escrito 16 marzo 2009 - 02:36

...Yo me imagino tener 24 hilos creados y mantenerlos (aunque en la ayuda dicen que no es aconsejable tener más de 16). Mandarlos a suspender por tiempo y volverlos a ejecutar. No me parece demasiado viable crear y destruir cada dos pos tres...


En este caso no se debe usar la suspensión porque consume ciclos de procesador al llamar a las APIs necesarias las cuales "entran" hasta el nucleo. Crear y Destruir (el objeto) es tambien una mala idea ;)

Y ahora ando pensando si es bueno tener 24 hilos.... ¿porqué no uno como comentó Domingo? La pregunta que me hago es si es muy adecuado que atienda a todos... ¿"aguantará"?...


Pues seoane no especifico la cantidad de hilos, pero si utilizó el plural. Si crearas un solo hilo funcionaria, pero debes considerar que si todas las PCs estan "desconectadas" excepto la ultima, el retardo se incrementaria en cada repeticion y habria una respuesta de tiempo de ese unico equipo despues de un intervalo prolongado.


...Finalmente considero que el rango razonable de hilos por proceso para este tipo de aplicaciones es de 256 a 1024...


Salud.
  • 0

#33 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 16 marzo 2009 - 05:04

¡Muchas Gracias Chackall!, eso funciona de maravillas sólo me queda jugar con el canvas, una cosa, cuando hay echo no muestra "IP_SUCCESS", ¿es así­ expresamente?.

Saludos.

PD. por lo menos aprendí­ lo básico sobre los Threads :p
  • 0

#34 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 17 marzo 2009 - 10:13

...Yo me imagino tener 24 hilos creados y mantenerlos (aunque en la ayuda dicen que no es aconsejable tener más de 16). Mandarlos a suspender por tiempo y volverlos a ejecutar. No me parece demasiado viable crear y destruir cada dos pos tres...


En este caso no se debe usar la suspensión porque consume ciclos de procesador al llamar a las APIs necesarias las cuales "entran" hasta el nucleo. Crear y Destruir (el objeto) es tambien una mala idea ;)

Y ahora ando pensando si es bueno tener 24 hilos.... ¿porqué no uno como comentó Domingo? La pregunta que me hago es si es muy adecuado que atienda a todos... ¿"aguantará"?...


Pues seoane no especifico la cantidad de hilos, pero si utilizó el plural. Si crearas un solo hilo funcionaria, pero debes considerar que si todas las PCs estan "desconectadas" excepto la ultima, el retardo se incrementaria en cada repeticion y habria una respuesta de tiempo de ese unico equipo despues de un intervalo prolongado.


...Finalmente considero que el rango razonable de hilos por proceso para este tipo de aplicaciones es de 256 a 1024...


Salud.

Hola Javier, no comprendo del todo el código (para variar :p :D)... me llama la atención como es que se enganchan las cosas...

A ver si entiendo de manera superficial... Creas un hilo con la api CreateThread(), pasandole en el parámetro lpStartAddress la función Thead(). ¿En este parámetro se recibe el puntero a la rutina que debe ejecutar el Thread? ¿no?

La función Thread se encarga de crear una nueva ventana echo, luego encolas el mensaje WM_USER, pasandole como parámetro el í­ndice del thread... hasta allí­ vamos...
pero en el parámetro adicional lParam mandas un ¿echo request?

Déjame ver si logro entender allí­ el tema... el API IcmpSendEcho recibe como los dos primeros parámetros la ventana echo creada previamente con IcmpCreateFile y la estructura record TInAddr con la IP a donde hacer ping.... en el parámetro sexto (ReplyBuffer) el ¿puntero hacia una posición del array record que tu definiste?
Allí­ ya me pierdo... si me puedes aclarar ese punto te lo agradecerí­a.

Ya por último te pones a la escucha de los mensajes, que gracias al í­ndice WParam te pones tan hermosamente a ubicar correctamente el texto referente a cada ping e IP. Aquí­ tengo cierta curiosidad que tiene que ver con el uso de los mensajes... ¿No es necesario identificar si el mensaje es WM_USER? A lo que voy, es que tengo pensado (favor de corregirme, no se si estoy en lo correcto) que el método PingStatus va "capturando" todos los mensajes y no simplemente WM_USER. No se... en otros ejemplos que he visto... por lo general veo un condicional o un case para comprobar si el mensaje recibido es el que nos interesa...



delphi
  1. if Message.Msg = WM_USER then ....



Si tienes un poco de tiempo te agradecerí­a que me uniera los conceptos, o si tienes alguna referencia o fuente de la que pueda leer.

EDITO:
Por cierto... ese número de hilos que indicas es grande comparado con el que leo en la ayuda:

Keeping track of too many threads consumes CPU time; the recommended limit is 16 active threads per process on single processor systems.


Saludos,
  • 0

#35 cHackAll

cHackAll

    Advanced Member

  • Administrador
  • 599 mensajes

Escrito 17 marzo 2009 - 02:38

...cuando hay echo no muestra "IP_SUCCESS", ¿es así­ expresamente?...


Lo que sucede es que he obviado que el valor de Status tras haber realizado un éco serí­a IP_SUCCESS, sin embargo estaba en mi inconciente que no serí­a asi, por lo que Message.LParam será 0 solo si ocurrio un error, en tal caso deberás revisar el valor de Status para saber qué ha ocurrido.

Nota; aunque va en contra de la documentación es posible que Status sea 0 y no 11000, habra que revisar :^)

 

Delphius; Te explico brevemente, cuando se crea el formulario (FormCreate) defino los IPs de todos los elementos del vector Reply, aparte de lo obvio lo hice de esta forma para poder inicializarlos de forma no secuencial (Ej. 192.168.1.2, 192.168.2.1, 192.168.1.30).

Al momento de inicializarlos tambien creo un hilo por cada elemento y al hilo le paso como parametro el indice del elemento en el vector al que habra de manejar cada hilo procesa individualmente un elemento y por ende un IP, el resultado del éco junto con el indice es enviado al formulario en forma de mensaje.

Aqui tu pregunta, en la linea 13 de Unit1.pas esta el valor del mensaje que ha de procesar ; message WM_USER;. Esta es la forma en que el Delphi maneja los mensajes, y como ya habras confirmado solo maneja el mensaje definido (para procesar cualquier mensaje podrí­as optar por un case en Application.OnMessage).

Salud
  • 0

#36 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 17 marzo 2009 - 02:45

Hola

Me parece un asunto muy interesante esto de los mensajes del API

Encontré esto :



delphi
  1. Public Enum IP_STATUS
  2.     IP_STATUS_BASE = 11000
  3.     IP_SUCCESS = 0
  4.     IP_BUF_TOO_SMALL = (11000 + 1)
  5.     IP_DEST_NET_UNREACHABLE = (11000 + 2)
  6.     IP_DEST_HOST_UNREACHABLE = (11000 + 3)
  7.     IP_DEST_PROT_UNREACHABLE = (11000 + 4)
  8.     IP_DEST_PORT_UNREACHABLE = (11000 + 5)
  9.     IP_NO_RESOURCES = (11000 + 6)
  10.     IP_BAD_OPTION = (11000 + 7)
  11.     IP_HW_ERROR = (11000 + 8)
  12.     IP_PACKET_TOO_BIG = (11000 + 9)
  13.     IP_REQ_TIMED_OUT = (11000 + 10)
  14.     IP_BAD_REQ = (11000 + 11)
  15.     IP_BAD_ROUTE = (11000 + 12)
  16.     IP_TTL_EXPIRED_TRANSIT = (11000 + 13)
  17.     IP_TTL_EXPIRED_REASSEM = (11000 + 14)
  18.     IP_PARAM_PROBLEM = (11000 + 15)
  19.     IP_SOURCE_QUENCH = (11000 + 16)
  20.     IP_OPTION_TOO_BIG = (11000 + 17)
  21.     IP_BAD_DESTINATION = (11000 + 18)
  22.     IP_ADDR_DELETED = (11000 + 19)
  23.     IP_SPEC_MTU_CHANGE = (11000 + 20)
  24.     IP_MTU_CHANGE = (11000 + 21)
  25.     IP_UNLOAD = (11000 + 22)
  26.     IP_ADDR_ADDED = (11000 + 23)
  27.     IP_GENERAL_FAILURE = (11000 + 50)
  28.     MAX_IP_STATUS = 11000 + 50
  29.     IP_PENDING = (11000 + 255)
  30.     PING_TIMEOUT = 200
  31. End Enum



Donde 11000 es la base y a partir de ahí­ va generando los valores, 0 es Satisfactoria, los demás tienen un incremento.

Muy bueno e interesante el manejo que haces Little Bro (y)

Enlace

Salud OS
  • 0

#37 cHackAll

cHackAll

    Advanced Member

  • Administrador
  • 599 mensajes

Escrito 17 marzo 2009 - 03:00

...Encontré esto :



delphi
  1. Public Enum IP_STATUS
  2.     IP_STATUS_BASE = 11000
  3.     IP_SUCCESS = 0
  4.     IP_BUF_TOO_SMALL = (11000 + 1)
  5.  
  6. // . . .

...


Esa no es documentacion oficial amigo, IP_SUCCESS esta definida como 11000, sin embargo lo mejor antes de procesar el valor de Status es procesar e valor retornado por la API IcmpSendEcho que ha de ser diferente de 0 al haber realizado satisfactoriamente el éco.

...Muy bueno e interesante el manejo que haces Little Bro (y)...


Gracias amigo :)
  • 0

#38 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 17 marzo 2009 - 03:18


Delphius; Te explico brevemente, cuando se crea el formulario (FormCreate) defino los IPs de todos los elementos del vector Reply, aparte de lo obvio lo hice de esta forma para poder inicializarlos de forma no secuencial (Ej. 192.168.1.2, 192.168.2.1, 192.168.1.30).

Al momento de inicializarlos tambien creo un hilo por cada elemento y al hilo le paso como parametro el indice del elemento en el vector al que habra de manejar cada hilo procesa individualmente un elemento y por ende un IP, el resultado del éco junto con el indice es enviado al formulario en forma de mensaje.

Esa parte si la entendí­, se que creas un hilo por cada IP y vas asociando a cada hilo con el í­ndice del vector.
Mi duda pasaba mas que nada por como se enganchaba CreateThread() con las demás funciones y métodos.

Aqui tu pregunta, en la linea 13 de Unit1.pas esta el valor del mensaje que ha de procesar ; message WM_USER;. Esta es la forma en que el Delphi maneja los mensajes, y como ya habras confirmado solo maneja el mensaje definido (para procesar cualquier mensaje podrí­as optar por un case en Application.OnMessage).

Salud

¡Gracias! No habí­a visto ese pequeño detalle :p



delphi
  1. procedure PingStatus(var Message: TMessage); message WM_USER;



Saludos,
  • 0

#39 Kipow

Kipow

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 228 mensajes
  • LocationGuatemala

Escrito 18 marzo 2009 - 06:38

deberas excelente codigo chackall, nada de vcl, con este tipo de codigo cada vez voy entendiendo mas lo de programar directo con las API
  • 0

#40 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4.483 mensajes
  • LocationVenezuela

Escrito 18 marzo 2009 - 09:33

simplemente digno de ti, excelente (y)

Aun no entiendo como no tienes un jugoso proyecto entre manos...
  • 0




IP.Board spam blocked by CleanTalk.