20/03/2006

idTcpClient pode ficar escutando os comandos do idTcpServer?

Ai pessoal, pelo que entendi os componentes indy funcionam em um meio de pergunta e resposta, certo?

O cliente faz uma pergunta o servidor responde, o servidor faz uma pergunta o cliente responde e assim por diante. Se o cliente fizer mais de uma pergunta por vez o servidor enviará uma reposta de cada vez até por que será feita uma resposta por vez:
IdTcpClient.WriteLn(‘#Comando’);
ShowMessage(idTcpClient.ReadLn());


Minha dúvida é a seguinte: Se eu quiser enviar um comando do cliente para o servidor basta colocar um botão e fazer:
idClient.WriteLn(‘HORA’); //um exemplo para pedir a hora do servidor
MsgResposta := idClient.ReadLn();//Aqui já pego a resposta do servidor, certo?

:arrow: :arrow: No servidor coloco no evento OnTcpServerExecute;
Var
Msg : String;
Begin
Msg := UpperCase(idTcpServer.ReanLn());
If Msg = ‘#HORA’ then // se o cliente estiver pedindo a hora envio para ele uma resposta...
 idTcpServer.WriteLn(Time); 
…

Resumindo, sabemos que para ler as solicitações do cliente basta colocar uma instrução neste evento no servidor, certo? Mais e no cliente, como faço para aguardar os comandos do servidor. Tentei colocar um timer para ficar assim: :idea: :idea: :idea:
var
 msg : String;
begin
msg := ´´;
if IdTCPClient.Connected then
 begin
  msg := IdTCPClient.ReadLn();
  if msg <>´´ then
   begin
    ListBox1.Items.Add(msg);
   end
  else
   begin
    Exit;
   end;
 end;
end;
só que a minha aplicação trava quando não há nenhuma mensagem vinda do servidor!... :!: :!: :!:

Minha pergunta é tem como o cliente ficar escutando os comandos do servidor, sem ser nas seqüências abaixo?
IdTcpClient.WriteLn(‘#Comando’);
ShowMessage(idTcpClient.ReadLn());

:?: :?: :?:


Paullsoftware

Respostas

20/03/2006

Massuda

Talvez [url=http://forum.clubedelphi.net/viewtopic.php?t=70214]este tópico[/url] seja útil para você. Tem dois modos de resolver isso, uma é usando uma thread para o cliente ler o que chega do servidor ou você usar um TIdTCPServer também no cliente. Na versão 10 do Indy tem novos recursos para suportar isso, mas eu não conheço como usar (não uso a versão 10).


Responder Citar

20/03/2006

Paullsoftware

Massuda, tentei implementar seu o código do Tópico que vc informou, mais não compila, dar um erro nessa linha:
type
  TReadingThread = class(TThread)
    protected
    FConn: TIdTCPConnection;
    procedure Run; override;//aqui da o erro!
    public
    constructor Create(AConn: TIdTCPConnection); reintroduce;
    end;
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Edit1: TEdit;
    Button1: TButton;
    IdTCPClient: TIdTCPClient;
    SpeedButton1: TSpeedButton;
    Edit2: TEdit;
    SpinEdit1: TSpinEdit;
...


só resaultando, copiei e colei o código para testar! :roll:


Responder Citar

20/03/2006

Massuda

:oops: Onde está [i:80eabd98ea]procedure Run[/i:80eabd98ea], é [b:80eabd98ea]procedure Execute[/b:80eabd98ea].


Responder Citar

20/03/2006

Paullsoftware

:oops: Onde está [i:09d8228d08]procedure Run[/i:09d8228d08], é [b:09d8228d08]procedure Execute[/b:09d8228d08].

Reader.TerminateAndWaitFor;

aqui também é só terminate?? :?: :?:


Responder Citar

20/03/2006

Massuda

Olhei novamente o código que está no outro tópico e percebi que a classe TReadingThread é derivada de TIdThread e não de TThread, como você fez; o código original deve funcionar se você mudar isso.

Se preferir continuar a derivar de TThread, o TIdThread.TerminateAndWaitFor corresponde a chamar TThread.Terminate seguido de TThread.WaitFor.


Responder Citar

20/03/2006

Paullsoftware

funcinou, mais eu coloquei um timer para ficar testando a conexão assim:
if idTcpClient.Connected then
Reader := TReadingThread.Create(IdTCPClient);
setei o interval para 500, na procedure [b:e330f01584]Execute[/b:e330f01584] coloquei para tratar os comandos que vem do servidor e se não for reconhecido to dando um [b:e330f01584]Exit[/b:e330f01584] será que to fazendo certo :?: :?: :?:


Responder Citar

20/03/2006

Massuda

Não entendi porque você está usando um timer. Não precisa. A thread, depois de ser criada, vai executar sempre que chegar algo do servidor e irá terminar quando houver desconexão.


Responder Citar

20/03/2006

Paullsoftware

Não entendi porque você está usando um timer. Não precisa. A thread, depois de ser criada, vai executar sempre que chegar algo do servidor e irá terminar quando houver desconexão.

então isso é estranho não está funcionando assim...
vou fazer mais alguns testes e post o resultado! :wink:


Responder Citar

20/03/2006

Paullsoftware

realmente massuda a Trhade é criada, mais não esta funcionando, alias, só funciona no momento da conexão da estação com o servidor...
quando conecto a estação vem na hora a resposta do cliente:
idTcpServer.WriteLn(´Conectado com Sucesso!´);

mais depois disso se enviar algum comando do servidor não é executado, comente quando o cliente faz uma nova solicitação é mostrar a mensagem que o servidor havia enviado antes.. já quando eu coloco o timer, menseionado anteriormente funciona! o que pode ser?


Responder Citar

20/03/2006

Paullsoftware

depois de fazer alguns testes, cheguei a esse código:
procedure TReadingThread.Execute;
var
  Command: String;
begin
 With fMain do
  begin
  if not IdTCPClient.Connected then Exit;
  repeat
    Command := UpperCase(FConn.ReadLn);
    if Command = ´#NET´ then FConn.WriteLn(´Desconectado do Servidor´)//ShowMessage(´Desconectado do Servidor´)
    else if Command = ´BLOCK´ then FConn.WriteLn(´Executado com sucesso!´)//ShowMessage(´Terminal Bloqueado´)
    else if Command = ´SHUTDOWN´ then FConn.WriteLn(´Executado com sucesso!´)//ShowMessage(´Desligar Terminal´)
    else if Command = ´LIBERA´ then FConn.WriteLn(´Executado com sucesso!´)//ShowMessage(´Terminal Liberado´)
    else if Command = ´REBOOT´ then FConn.WriteLn(´Executado com sucesso!´)//ShowMessage(´Reiniciar Terminal´)
    else if Command = ´TELA´ then FConn.WriteLn(´Executado com sucesso!´)//ShowMessage(´Enviar Tela do Terminal´)
    else if Command = ´#STOP´ then FConn.WriteLn(´Executado com sucesso!´);//ShowMessage(´Parar Tempo´);
    ListBox1.Items.Add(Command);
    Command := ´´;
  until not IdTCPClient.Connected;
  end;
end;

a principio esta funcionando corretamente, mais o estranho é que quando estava usando as [b:84b1f1c973]ShowMessages();[/b:84b1f1c973] não estava funcionando, sabe informar pq? :?: :?: :?:


Responder Citar

20/03/2006

Massuda

...quando estava usando as [b:274e51508e]ShowMessages();[/b:274e51508e] não estava funcionando, sabe informar pq?
Porque é uma thread! Todo programa Delphi tem uma thread principal que cuida da interface com o usuário (vulgarmente, a ´tela´); qualquer outra thread que você cria e que precisa acessar a interface com o usuário precisa fazer isso de forma sincronizada (duas threads não podem usar a tela simultaneamente); veja na ajuda do Delphi o método TThread.Synchronize.


Responder Citar

20/03/2006

Paullsoftware

certo, Massuda...
valeu pelos toques, agora acho que vai dar pra continuar o desenvolvimento do projeto! :wink: obrigado mais uma vez...
problema solucionado! :twisted: :twisted:


Responder Citar

21/03/2006

Paullsoftware

Op´s surgiu outras dúvidas...

como desconectar ou enviar mensagem para todos os usuários conectados ao servidor???

não achei nos exemplos que olhei sobre o indy...


Responder Citar

21/03/2006

Massuda

Um exemplo simples seria...
var 
  List: TList; 
  Peer: TIdPeerThread; 
... 
  List := IdTCPServer1.Threads.LockList; //isso bloqueia o servidor! 
  try 
    for I := 0 to List.Count - 1 do begin 
      // List[I&93; é uma das threads do servidor 
      Peer := TIdPeerThread(List&91;I&93;); 
      Peer.Connection.WriteLn(´Oi´); 
    end; 
  finally 
    IdTCPServer1.Threads.UnlockList; 
  end;
...note que entre o LockList e o UnlockList o servidor ficará bloqueado se alguém tentar conectar no servidor; isso acontece porque o servidor precisa incluir um no TIdPeerThread na lista Threads, mas esse código bloqueia a lista temporariamente; moral da estória: seja lá o que você for fazer com cada Peer, procure evitar executar cosias demoradas.


Responder Citar

21/03/2006

Paullsoftware

seja lá o que você for fazer com cada Peer, procure evitar executar cosias demoradas.
eu to pensando em algo como:
1 - Desconectar todos os Clientes;
2 - Desligar Todos os Clientes;
3 - Reiniciar Todos os Clientes;
4 - Liberar Todos os Clientes
algo desse tipo, tem problemas???


Responder Citar