Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Internet (https://www.clubdelphi.com/foros/forumdisplay.php?f=3)
-   -   Mensaje de cliente a Servidor (https://www.clubdelphi.com/foros/showthread.php?t=28996)

NickName 10-01-2006 06:23:29

Mensaje de cliente a Servidor
 
Hola.

Despues de buscar varios dias en el foro y no encontrar algo que se paresca a mi problema que tengo me decidi por hacer esta pregunta.

Bueno primero uso Delphi7 y las Indy 9, y me encuentro desarrollando un sistemita para un cyber, Tengo una AplicacionCliente con un TIdTCPClient y tambien una AplicacionServidor con un TIdTCPServer y un TIdThreadMgrDefault.

Código:

//--- Mi bloc de comunicaciones lo uso en ambas partes (AppServer+AppCliente)
  TComunicacion = record
                Comando,
                NombreUsuario,                // Quien manda el mensaje
                Msg,                          // El Mensaje
                NombreReceptor: string[100];  // Nombre del Receptor
                Pc            : Integer;      // Numero de la Pc que envia
              end;

Todo funciona bien puedo mandar informacion desde mi cliente hasta el servidor y del servidor al cliente tambien:
Del cliente al servidor lo hago asi:
Código:

procedure TFrm_Principal.Button1Click(Sender: TObject);
Var
commBlock :TComunicacion;
begin
        //-- Asignar datos del bloc de comunicación
        CommBlock.Comando      := 'MENSAJE';
        CommBlock.NombreUsuario  := Client.LocalName;
        CommBlock.Msg            := 'Hola esto es una prueba :))))';
        CommBlock.NombreReceptor  := 'SERVIDOR';
        CommBlock.Pc              :=Num_Pc;
              // ---- Mandarlo ----
       
Client.WriteBuffer (CommBlock, SizeOf (CommBlock), true);

end;

Del servidor hacia el cliente hago algo parecido, mi problema es en el procedimiento Execute del Servidor al leer un mensaje del cliente si lo muestro en un Memo en el formulario principal no hay ningun problema pero lo que yo quiero es mostrar el mensaje que el cliente manda en un formulario distinto al principal, cuando muestro el mensaje el servidor se queda colgado y creo que tengo mi cerebro bloqueado ya que no encuentro la forma de mostrar el mensaje en otro formulario sin que mi servidor se cuelgue.... si alguien me puede iluminar un poco se lo agradeceria mucho... les pongo el codigo del procedimiento:
Código:

procedure TFrm_Principal.ServerExecute(AThread: TIdPeerThread);
var
  RecClient: PCliente;
  CommBlock, NewCommBlock: TComunicacion;
  RecThread: TIdPeerThread;
  i: Integer;
begin
  If Not AThread.Terminated And AThread.Connection.Connected Then
  Begin
        AThread.Connection.ReadBuffer (CommBlock, SizeOf (CommBlock));
        If (CommBlock.Comando = 'MENSAJE') Or (CommBlock.Comando = 'COMANDO') Then
          Begin
                // es el mismo código para ambas órdenes
              If CommBlock.NombreReceptor = '' Then
                Begin  // ningún destinatario dado se envia a todos los usuarios
                      NewCommBlock := CommBlock;  // No cambiar nada  ;-))
                      With Clientes.LockList Do
                        Try
                            For i := 0 To Count-1 Do  // interactuar con la lista de clientes
                            Begin
                                RecClient := Items[i];          //Obtener el objeto cliente                                RecThread := RecClient.Thread;    // Obtener el hilo del cliente
                                RecThread.Connection.WriteBuffer(NewCommBlock, SizeOf(NewCommBlock), True);  // Enviar el paquete
                            End;
                        Finally
                        Clientes.UnlockList;
                      End;
                End
              Else
                Begin  //  receptor dado - busquelo y se le envía a él
                    If CommBlock.NombreReceptor = 'SERVIDOR' Then
                      Begin  // destinatario el servidor
                        Paquete:=CommBlock;
                        MostrarMensaje(Paquete); // aqui esta el problema
                      End
                    Else
                      Begin

                          NewCommBlock := CommBlock; // De nuevo no cambiar nada ;-))
                          With Clientes.LockList Do
                              Try
                                  For i := 0 To Count-1 Do
                                Begin
                                      RecClient:=Items[i];
                                      // No tenemos ninguna función de inicio de sesion por eso usamos el DNS
                                      If RecClient.DNS=CommBlock.NombreReceptor Then
                                          Begin
                                              RecThread:=RecClient.Thread;
                                              RecThread.Connection.WriteBuffer(NewCommBlock, SizeOf(NewCommBlock), True);
                                        End;
                                  End;
                              Finally

                              Clientes.UnlockList;
                          End;
                      End;
                End;
          End
        Else
          Begin
  // Comando desconocido
              NewCommBlock.Comando := 'MENSAJE';      // El mensaje que debe mostrarse en la pantalla del cliente
              NewCommBlock.NombreUsuario := 'ADMINISTRADOR';  // El nombre del servidor
              NewCommBlock.Msg := 'Comando desconocido: "'+CommBlock.Comando+'"'; 
              NewCommBlock.NombreReceptor := '[De vuelta al remitente]'; // innecesario
              AThread.Connection.WriteBuffer (NewCommBlock, SizeOf (NewCommBlock), true);  // y aqui va...
          End;
    End;
end;

el procedimiento que se ejecuta para mostrar la ventana del mensaje:

Código:

Procedure TFrm_Principal.MostrarMensaje(Pak : TComunicacion);
Begin
    Frm_Mensaje.Label1.Caption:= Pak.NombreUsuario;
    Frm_Mensaje.cxMemo1.Lines.Add('Mensaje: ' + Pak.Msg);
    Frm_Mensaje.ShowModal;
End;

:confused:

dec 10-01-2006 07:03:33

Hola,

Yo creo que el problema está en mostrar el formulario en donde se mostrará a su vez el mensaje de forma "modal". Es decir, ¿probaste mostrando el formulario con el método "Show", y, si quieres que permanezca por encima, cambiando su propiedad "FormStyle" a "fsStayOnTop"? En cualquier caso gracias por tu mensaje, pues contiene información que me parece interesante. A ver si es posible solucionar el problema. ;)

NickName 10-01-2006 21:34:25

Responder a tema
 
Hola.

Gracias por responder, ya probe con el metodo Show del Formulario pero cuando hago eso ni siquiera se muestra bien el formulario nadamas se pueden ver los Bordes y el mensaje con el boton no se pueden ver, y el servidor de todas formas se Bloquea.

Por otra parte con el metodo ShowModal se muestra bien el formulario del mensaje pero al darle click en el boton de Aceptar se cierra el formulario del mensaje y el servidor se Bloquea hasta que cierro el cliente que me mando el mensaje., Si yo ignoro el formulario del mensaje y doy click en cualquier parte del formulario principal puedo seguir trabajando en el servidor pero el formulario sigue visible si la propiedad FormStyle = fsStayOnTop, si esta propiedad la cambio a Normal el formulario desaparece, pero si mando otro mensaje del cliente ya no me muestra el formulario del mensaje en el servidor y este sigue Bloqueado...:confused:

Despues de cerrar el cliente que envia el mensaje puedo cerrar el servidor y me manda este mensaje:
Error de sistema. codigo 1400
El identificador de la ventana no es valido

Esto sucede con el metodo ShowModal.

Alguna otra idea :rolleyes:

jachguate 11-01-2006 02:12:11

No olvides que los servidores indy son multihilos, por lo que al ejecutarse el evento ServerExecute, esto se realiza en el hilo de la conexión con el cliente y todas las operaciones a realizar con la VCL en la interfaz de usuario debén llevarse a cabo en el hilo principal de la aplicación, para lo que podes valerte del método Synchronize.

Saludos.

NickName 11-01-2006 02:15:59

Si se puede hacer
 
Hola.

Pues en vista de que no hay creo yo casos similares, le segui buscando y di con la respuesta y era algo sencillo, :p pero a falta de conocimiento entra la desesperacion.

Bueno ahora si puedo ver los mensajes sin ningun problema en el servidor con el metodo Show o ShowModal de mi formulario.

Pongo el codigo que cambio del primer mensaje que puse:
Código Delphi [-]
                     If CommBlock.NombreReceptor = 'SERVIDOR' Then
                       Begin  // destinatario el servidor
                         Paquete:=CommBlock;
                         AThread.Synchronize(MostrarMensaje); esto es lo que cambio
                       End

al procedimiento de mostrarmensaje solo le quite el parametro:
Código Delphi [-]
Procedure TFrm_Principal.MostrarMensaje;
Begin
     Frm_Mensaje.Label1.Caption:= Paquete.NombreUsuario;
     Frm_Mensaje.cxMemo1.Lines.Add('Mensaje: ' + Paquete.Msg);
     Frm_Mensaje.ShowModal;
End;

Y tube que usar AThread.Synchronize ya lo habia intentado pero el procedimiento de MandarMensaje tenia parametro y asi no se puede mandaba este error:
[Error] Principal.pas(426): There is no overloaded version of 'Synchronize' that can be called with these arguments
lo quite y jejeje Papitas...:D

NickName 11-01-2006 02:27:51

Responder a tema
 
Hola.

jachguate
Cita:

para lo que podes valerte del método Synchronize
Tienes razon jachguate, muchas gracias cuando lei tu mensaje ya habia escrito la respuesta pero de todas formas muchas gracias ya que con tu mensaje ibamos a dar creo yo al mismo resultado ;)


La franja horaria es GMT +2. Ahora son las 15:19:41.

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