Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Internet (https://www.clubdelphi.com/foros/forumdisplay.php?f=3)
-   -   Aplicación Cliente/Servidor no bloqueante (https://www.clubdelphi.com/foros/showthread.php?t=67770)

vejerf 05-05-2010 19:51:17

Aplicación Cliente/Servidor no bloqueante
 
Hola a tod@s,

Estoy desarrollando una aplicación cliente/servidor. Cuando el cliente se conecta al servidor le envía toda la información que este posee y cada vez que la renueva se la reenvía.

El problema me ha surgido cuando estando el programa corriendo el ordenador con la aplicación servidora se me ha reiniciado y esto no le ha gustado para nada a la aplicación cliente que se me ha quedado completamente colgada.

Estoy usando los componentes indy TIdTCPServer y el TIdCmdTCPClient.

No sé si lo que me ha pasado tiene que ver con que son componentes que establecen sockets bloqueantes y por ahí he leído que lo suyo es ponerlo a trabajar con hilos pero no tengo ni idea de como hacerlo.

Si no es por esto supongo que el corte súbito sin realizar la desconexión es lo que me ha causado este problema, pero como podría controlar esto?

Muchas gracias a todos!!!

manuc 05-05-2010 20:11:16

Hola vejerf,

Si se te ha quedado "congelado" el cliente, es probable que sea porque esté haciendo un read en el buffer. Como el servidor no llega a responder, el cliente se queda esperando a que le llegue información por el buffer.

Lo del hilo es buena idea, ya que la lectura y escritura del cliente quedaría en un segundo plano y no te congelaría el hilo principal, que es el que atiende las peticiones del usuario.

No obstante, hacer un hilo tiene sus dificultades y tienes que dominar muy bien la técnica para que todo te funcione correctamente.

Una cosa que puedes intentar y que será más fácil es a indicar un TimeOut de lectura del buffer:
Código Delphi [-]
IdTCPClient1.ReadTimeout := 1000;

Para mayor seguridad, lo podrías implementar también el servidor, para cuando se te de el caso contrario.

Ya me cuentas cómo te va con esto. Si no te soluciona tu problema, comentamos cómo lo podrías hacer un un hilo secundario.

Espero que te ayude.

Un saludo.

vejerf 06-05-2010 11:33:25

Hola Manuc,
Primero darte las gracias por tu respuesta y segundo comentarte un par de dudas que sigo tenido a ver si saber resorvérmelas.

Supongo que la propiedad ReadTimeout es el máximo tiempo que espera el componente para realizar una lectura. Pero tengo la duda sobre lo que ocurre si pasa este tiempo, no sé si se aborta la lectura o se cierra la conexión.

Suponiendo que se cierre la conexión entonces debería hacer que tanto el cliente como el servidor se envíen algún mensaje cada cierto tiempo diciendo "estoy vivo".

Voy a implementar esto y si no me funciona pues supongo que tendré que recurrir a los hilos, que aunque más complicado como dices creo que debe ser la solución más apropiada para estos casos.

Por otra parte tengo otra duda que no sé si sabrás respondérmela y es que yo para comunicarme usaba:
Código Delphi [-]
Cliente.IOHandler.WriteLn(Trama);

Sin embargo he visto que también posee la propiedad Socket con lo que se podría hacer supongo:
Código Delphi [-]
Cliente.Socket.WriteLn(Trama)

¿Qué diferencia hay entre una forma y otra si hay alguna?

Muchas gracias de nuevo!!!

manuc 08-05-2010 09:43:30

Hola vejerf,

Ciertamente "ReadTimeout" te desconectará del servidor tras superar el periodo de inactividad.

En una aplicación cliente que tiene que estar constantemente "escuchando" al servidor, es un complicado decidir qué tiempo es el más razonable para establecer el ReadTimeout.

Por un lado, si estableces un timeout muy pequeño, tendrás que hacer lo que comentas, generar actividad simplemente para que los hilos no se desconecten, con el riesgo de crear tráfico de red innecesario.

Por otro lado, si lo estableces muy alto, cuando tu servidor se cuelgue, el cliente tardará tiempo en darse cuenta y se quedará congelado.

Pero una pregunta: ¿tu software cliente está constantemente esperando respuesta por el servidor? o ¿es el servidor el que espera comandos y emite respuetas al cliente?

Respecto a la diferencia entre IOHandler y Socket, no sabría decirte qué diferencias existe entre ambos.

Un saludo.

vejerf 10-05-2010 09:57:56

Hola de nuevo Manuc,

Te cuento un poco de que va la aplicación. Resulta que estamos desarrollando una aplicación que controla la actualización de unos elementos en una sede. Pues resulta que hay varias sedes y una sede central. La idea es realizar una aplicación para las distintas sedes y una para la central. La central recibirá toda la información de las otras sedes cuando estas se conecten y cuando actualicen algún elemento.

Mi idea ha sido hacer una aplicación basada en TCP donde las distintas sedes tengan una aplicación cliente que se conectarán a la sede central donde residirá la aplicación servidora, pero en principio esta no tiene por qué enviar nada sino sólo los clientes enviarán información cuando se actualice algún elemento.

Esta es la filosofía básica de funcionamiento. Después cada elemento de cada sede se pueden actualizar a intervalos de 15min o incluso más por lo que es difícil estimar un tiempo.

Saludos!

manuc 10-05-2010 10:33:06

Hola vejerf,

Atendiendo a lo que me comentas, mi recomendación seria que cada cliente conecte al servidor, solo, cuando tenga algo para enviar al mismo.

El protocolo sería algo así:
- El cliente detecta cambios para enviar al servidor.
- Conecta al servidor.
- Establece el "ReadTimeout".
- Envía la información al servidor.
- Espera el "OK" del servidor
- Desconecta del servidor.

Por otro lado, el servidor al recibir la conexión también debe establecer la propiedad "ReadTimeout" de la conexión, para evitar que se queden hilos colgados en el servidor (cuando un cliente pierda la conexión de forma inesperada).

Sin querer me he encontrado un ejemplo de idTCPClient que casualmente utiliza un hilo secundario en la aplicación cliente.

Te lo dejo aquí por si te interesa verlo.

Realmente todo esto depende mucho de la estructuración de tu proyecto, de la cantidad de "paquetes" a enviar al servidor, de lo que el servidor tenga que hacer con esos paquetes, etc.

Espero que te ayude.

Un saludo.


La franja horaria es GMT +2. Ahora son las 21:31:19.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi