Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Internet
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 21-04-2007
JMGR JMGR is offline
Miembro
 
Registrado: jun 2003
Ubicación: Santa Cruz de Tenerife
Posts: 46
Poder: 0
JMGR Va por buen camino
Question Actualizar form mientras se reciben datos por sockets

Buenas...

Tengo una aplicacion cliente/servidor por sockets usando los componentes de Delphi. Los clientes pueden ser varios y, entre otras cosas, mandar determinados archivos al servidor, y he aqui el problema, cuando un cliente manda un archivo, el servidor va rellenando un stream con los datos recibidos mediante un bucle while, y claro, durante este proceso el form no se actualiza ni me permite seguir con otro cliente...

La idea seria que mientras se este recibiendo un archivo de un cliente el servidor se pudiera comunicar con cualquier otro cliente, no necesariamente para enviar/recibir otro archivo aunque si es posible mejor.

No me vale application.processmessages porque entonces se me interrumpe la transferencia...

Este es el bucle, ubicado en el evento OnRead del serversocket:
Código Delphi [-]
try
  while true do
     begin
       nReceived := Socket.connections[j].ReceiveBuf (Buffer, sizeof (Buffer));
       if nReceived <= 0 then
         Break
        else
          Stream.Write (Buffer, nReceived);
          //application.ProcessMessages;<--Si lo pongo se interrumpe la transferencia
           pb1.StepIt;
           Sleep (500);
     end;
    Stream.Position := 0;
    if directorio[Length(directorio)]<>'\' then
    directorio:=directorio+'\';
    stream.SaveToFile(directorio+archivo);
    socket.connections[j].SendText('DOWN');
 finally
 end;

¿Hay otra manera de rellenar el stream sin un bucle while?
¿Se puede actualizar el form sin interrumpir la transferencia?

Me imagino que una alternativa seria usar Threads pero no hay manera de entender como funcionan...
Otra cosa que he descubierto despues de bastantes cabreos es que si en la linea:
Código Delphi [-]
 Sleep (500);
Pongo:
Código Delphi [-]
Sleep (200);

Entonces no me llegan los archivos completos, variando la cantidad de datos recibida segun...

¿Alguna idea?
Gracias y un saludo.
JMGR
Responder Con Cita
  #2  
Antiguo 21-04-2007
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Estas haciendo muchas suposiciones, sobre el tiempo que tardan en llegar los paquetes. No se si has probado el programa dentro de una red de verdad, poniendo el servidor y el cliente en equipos diferentes, si lo haces veras que los paquetes puedes sufrir retardos imprevisibles, así que hacer suposiciones sobre los milisegundos te llevara a errores.

Por otro lado supongo que estas usando sockets que no se bloquean, asíncronos. Estos son muy cómodos, pues solo tienes que esperar a que la información vaya llegando y el evento OnRead se dispara todas las veces que eso ocurra. El problema es que tu quieres leer todos los datos de una vez, y precisamente los sockets asíncronos se utilizan para ir leyendo la información según va llegando, en diferentes eventos. Así que lo que deberías hacer es usar, por ejemplo, variables globales.

Dicho esto, yo te recomiendo los socket que se bloquean usados junto con threads. El concepto es mucho mas sencillo, cada conexion es un hilo de ejecucion diferente, y los datos se leen y escriben de forma sincrona. Para mi es mucho mas facil de entender el modelo sincrono que el asincrono, pero a la gente parece que le gusta mas lo asincrono

Ya se que lo anterior es un rollo, así que mi consejo es que si quieres hacer algo mas complejo que mandar mensajitos de texto, te olvides del TClientSocket y TServerSocket y utilices los componentes Indy, y mejor si utilizas un componente con un protocolo como ftp, http. Y si lo sigues queriendo hacer por el camino difícil, entonces dejate de tonterías y vamos directamente a la api, donde crearemos los socket "a mano" y leeremos, escribiremos y comprobaremos su estado usando funciones de la api. Esto que en principio resulta muy trabajoso, luego nos da mucho mas control sobre la comunicación.

Espero que te sirva, y perdona por el rollo ...
Responder Con Cita
  #3  
Antiguo 21-04-2007
JMGR JMGR is offline
Miembro
 
Registrado: jun 2003
Ubicación: Santa Cruz de Tenerife
Posts: 46
Poder: 0
JMGR Va por buen camino
Gracias por la respuesta seoane, te comento:
Cita:
No se si has probado el programa dentro de una red de verdad, poniendo el servidor y el cliente en equipos diferentes, si lo haces veras que los paquetes puedes sufrir retardos imprevisibles, así que hacer suposiciones sobre los milisegundos te llevara a errores.
Si, he probado la aplicacion tanto en red local como en internet y me ocurria que, en red si me llegaban enteros los archivos, mientras que en internet no, hasta que aumente el tiempo a 500, ahora entiendo el por qué, pero claro, con ese tiempo las transferencias son bastante lentas...

Cita:
mi consejo es que si quieres hacer algo mas complejo que mandar mensajitos de texto, te olvides del TClientSocket y TServerSocket y utilices los componentes Indy, y mejor si utilizas un componente con un protocolo como ftp, http.
En un principio intente usar los Indy ya que habia leido por aqui que eran los recomendables pero no encontre ninguna demo de TCP/IP, aparte de que la version que tengo yo de las Indy, la 10, ya no trabaja con Threads sino con IdContext, asi que no me aclare y me decidi por los sockets normalitos...se ve que no fue mi mejor idea...

Dado que mi intencion si que es hacer algo mas que mandar mensajitos voy a ponerme a investigar con los Indy a ver que pasa, y de paso ver si encuentro un ejemplo de sockets asincronos y threads y a ver que veo mas asequible.

Ya dare el coñazo por aqui con las dudas que me surjan...
Gracias por el "rollo"
Un saludo.
JMGR
Responder Con Cita
  #4  
Antiguo 23-12-2011
genyus00 genyus00 is offline
Miembro
 
Registrado: jun 2010
Posts: 29
Poder: 0
genyus00 Va por buen camino
Solucion

usa application.processmessage o simula el while con un timer.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Desactivar un form mientras se ejecuta otra aplicación hvelascos Internet 2 19-01-2007 01:50:41
Actualizar datos de una base de datos en un reporte Marymania Impresión 4 27-11-2006 19:47:32
Actualizar datos en un Qreport royrogers84 Varios 6 21-11-2006 23:46:09
Como leer los paquetes que se reciben por el puerto COM rjsitruiz Varios 5 07-08-2004 00:07:10
Actualizar Datos trex2000 Firebird e Interbase 1 26-09-2003 23:21:49


La franja horaria es GMT +2. Ahora son las 16:27:13.


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
Copyright 1996-2007 Club Delphi