idTcpClient pode ficar escutando os comandos do idTcpServer?

20/03/2006

0

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

Paullsoftware

Responder

Posts

21/03/2006

Massuda

Aparentemente em todos os casos o cliente vai ter que desconectar do servidor. Pelo que entendi, não teria problemas, pois você vai apenas mandar um comando e acredito que não há necessidade de esperar o cliente executar o comando.


Responder

21/03/2006

Paullsoftware

Aparentemente em todos os casos o cliente vai ter que desconectar do servidor. Pelo que entendi, não teria problemas, pois você vai apenas mandar um comando e acredito que não há necessidade de esperar o cliente executar o comando.
a ta, agora entendi, vc é que sempre que há o envio por parte de um deles client/servidor na sequencia eles ficam aguardando uma resposta do outro né isso?
eu imaginei isso também, por exemplo eu pensei em pedir dos clientes com o comando [b:1c03103f21]#HORA[/b:1c03103f21] por exemplo, mais ai pensei: ele vai pedir a hora de todos e depois que o último receber o pedido é que ele vai processar a do primeiro, estou certo?


Responder

21/03/2006

Massuda

Talvez eu não tenha entendido, mas eu implementaria, por exemplo, o comando DESLIGAR assim....
// código no servidor
var 
  List: TList; 
  Peer: TIdPeerThread; 
... 
  List := IdTCPServer1.Threads.LockList; 
  try 
    for I := 0 to List.Count - 1 do begin 
      // List[I] é uma das threads do servidor 
      Peer := TIdPeerThread(List[I]); 
      Peer.Connection.WriteLn(´DESLIGAR´); 
      if Peer.Connection.ReadLn(10, 100) <> ´OK´ then begin
        // loga/avisa que não respondeu
      end;
    end; 
  finally 
    IdTCPServer1.Threads.UnlockList; 
  end;

// código no cliente
...
  Comando := IdTCPClient1.ReadLn;
  if Comando = ´DESLIGAR´ then begin
    IdTCPClient1.WriteLn(´OK´);
    //prepara para desligar
  end
...
...isso deve funcionar sem problemas no seu caso (lan house né?), onde o número de clientes ligados ao servidor é fixo.


Responder

21/03/2006

Paullsoftware

Massuda, eu crei uma procedure no servidor para enviar o comando par ao cliente assim:
procedure TfMain.SendAll(wTipo:String);
var
 List : TList;
 Peer : TIdPeerThread;
 I    : Integer;
begin
 List := TCPServer.Threads.LockList;
 try
   for I := 0 to List.Count -1 do
    begin
     Peer := TIdPeerThread(List[i]);
     if wTipo = UpperCase(´:1´) then
      begin
       Peer.Connection.WriteLn(´TELA´)
      end
     else
     if wTipo = UpperCase(´:2´) then
      begin
       Peer.Connection.WriteLn(´STOP´)
      end
     else
     if wTipo = UpperCase(´:3´) then
      begin
       Peer.Connection.WriteLn(´BLOCK´)
      end
     else
     if wTipo = UpperCase(´:4´) then
      begin
       Peer.Connection.WriteLn(´LIBERA´)
      end
     else
     if wTipo = UpperCase(´:5´) then
      begin
       Peer.Connection.WriteLn(´#REBOOT´)
      end
     else
     if wTipo = UpperCase(´:6´) then
      begin
       Peer.Connection.WriteLn(´MSG´)
      end
     else
    end;
 finally
   TCPServer.Threads.UnlockList;
 end;
end;


e no client tenho uma Trhead assim:
procedure TReadingThread.Execute;
var
Command,cmd : String;
begin
With fMain do
begin
repeat
Command := UpperCase(FConn.ReadLn);
cmd := Command;
if Command = ´NET´ then
begin
FConn.WriteLn(IdTCPClient.Socket.LocalName+ ´ Desconectado do Servidor´);
lbStatus.Items.Insert(0,Command);
end;
if Command = ´BLOCK´ then
begin
FConn.WriteLn(IdTCPClient.Socket.LocalName+ ´ Bloqueado com sucesso!´);
lbStatus.Items.Insert(0,Command);
end;
if Command = ´#SHUTDOWN´ then
begin
FConn.WriteLn(IdTCPClient.Socket.LocalName+ ´ Desligado com sucesso!´);
lbStatus.Items.Insert(0,Command);
end;
if Command = ´LIBERA´ then
begin
FConn.WriteLn(IdTCPClient.Socket.LocalName+ ´ Liberado com sucesso!´);
lbStatus.Items.Insert(0,Command);
end;
if Command = ´REBOOT´ then
begin
FConn.WriteLn(IdTCPClient.Socket.LocalName+ ´ Reiniciado com sucesso!´);
lbStatus.Items.Insert(0,Command);
end;
if Command = ´TELA´ then
begin
FConn.WriteLn(´Tela copiado da Estação: ´ + IdTCPClient.Socket.LocalName);
lbStatus.Items.Insert(0,Command);
end;
if Command = ´STOP´ then
begin
FConn.WriteLn(IdTCPClient.Socket.LocalName+ ´ Tempo parado com sucesso!´);
lbStatus.Items.Insert(0,Command);
end;
cmd := UpperCase(Trim(Copy(cmd, 1, Pos(´:´, cmd)-1)));
if cmd = ´!´ then
begin
lbStatus.Items.Insert(0,´Liberado!´);
Button2.Enabled := True;
end
else
if cmd = ´?´ then
begin
lbStatus.Items.Insert(0,Command);
Button2.Enabled := False;
end;
until not IdTCPClient.Connected;
end;
end;
lembra? Ela ainda está incompleta, mais estou desenvolvendo primeiro o server, e fiz o código acima somente para testar, ainda não tá 100¬, mais acho que o caminho é por ai...
Eu tava olhando um dia desses o [b:11672851a1]Projeto Lan-House[/b:11672851a1], mais percebi que o pessoal abandonou ou estão se comunicando por outro lugar, pois, as mensagens que estão lá são muito antigas...


Responder

21/03/2006

Massuda

...eu crei uma procedure no servidor para enviar o comando par ao cliente assim...mais acho que o caminho é por ai...
É isso mesmo.


Responder

21/03/2006

Paullsoftware

[quote:b9ee474c3d=´paullsoftware´]...eu crei uma procedure no servidor para enviar o comando par ao cliente assim...mais acho que o caminho é por ai...
É isso mesmo.[/quote:b9ee474c3d]

Obrigado mais uma vez grande amigo Massuda! qq coisa resgato esse tópico! :roll:


Responder

24/03/2006

Paullsoftware

Grande Massuda :wink:
resolvi resgatar esse tópico, para ficar tudo em um único local, estou com outra dúvida e não sei se é possível fazer essa fasanha...

como faço para pegar o nome da estação através do servidor, digo isso porque estou fazendo assim:
wEstacao := IdTCPClient.Socket.LocalName +´ - ´+IdTCPClient.Socket.Binding.IP;

quando o cliente manda algo para o server em envio junto o nome dele, mais gostaria de saber se tem como fazer isso através do servidor mesmo..
como os Sockets fazem... RemotHost e RemotAddress, é possível fazer com indy :?: :?:


Responder

24/03/2006

Massuda

Normalmente eu pego esse tipo de informação no evento OnConnect do TIdTCPServer usando algo do tipo...
procedure TExemplo.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
  // AThread.Connection.Socket.Binding.PeerIP = IP do cliente
  // AThread.Connection.Socket.Binding.PeerPort = porta do cliente
end;
...mas não sei dizer como pegar, via Indy, o nome do cliente (normalmente eu uso apenas o IP e a porta).


Responder

24/03/2006

Paullsoftware

Normalmente eu pego esse tipo de informação no evento OnConnect do TIdTCPServer usando algo do tipo...
procedure TExemplo.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
  // AThread.Connection.Socket.Binding.PeerIP = IP do cliente
  // AThread.Connection.Socket.Binding.PeerPort = porta do cliente
end;
...mas não sei dizer como pegar, via Indy, o nome do cliente (normalmente eu uso apenas o IP e a porta).


certo, hoje eu to fazendo como disse acima, na hora que o cliente conecta envio a seguinte informação:
var
wEstacao:String;
begin
...
wEstacao := IdTCPClient.Socket.LocalName +´ - ´+IdTCPClient.Socket.Binding.IP;
SendCmd(´+´,wEstacao);//onde SendCmd é um procedure que criei para enviar mensagens para o servidor com um determinado identificador seria o mesmo que: [b:def03de3b4][i:def03de3b4]IdTCPClient.WriteLn(´+;´ + wEstacao);[/i:def03de3b4][/b:def03de3b4]. Então, eu envio essas informações e o server trata elas assim:
procedure TfMain.TCPServerConnect(AThread: TIdPeerThread);
var
  Client  : TSimpleClient;
  Cmd,Msg : String;
begin
  Msg := AThread.Connection.ReadLn();
  Cmd := Trim(Copy(Msg, 0, Pos(´:´, Msg) -1));
  Msg := Trim(Copy(Msg, Pos(´:´, Msg) +1, Length(Msg)));
  if Cmd = ´+´ then
   begin
    AThread.Connection.WriteLn(´;: NOME DA ESTAÇÃO NA REDE: ´+Msg);
    AThread.Connection.WriteLn(´#BLOCK´);
    Client := TSimpleClient.Create;
    Client.Name := Trim(Copy(Msg, 0, Pos(´-´, Msg) -1));
    Client.DNS  := Trim(Copy(Msg, Pos(´-´, Msg) +1, Length(Msg))); ;
    Client.ListLink := lbClients.Items.Count;
    Client.Thread := AThread;
    lbClients.Items.Add(Client.Name+ ´ - ´+Client.DNS);
    AThread.Data := Client;
    Clients.Add(Client);
    lbStatus.Items.Insert(0,UpperCase(Client.Name)+ ´ Conectou agora: ´ + FormatDateTime(´DD/MM/YYYY HH:MM:SS´,Now) );
   end;

só que pensei que haveria uma fora de ´pegar´ o nome/ip do cliente e não ´ler´ como fasso. mais valeu...
estou pensando em fazer tudo no server (banco/programação/comandos/contagem do tempo, etc...) tudo no server, nos clientes pensei em mandar somente o exe... seria vantagioso? :roll:


Responder

24/03/2006

Massuda

só que pensei que haveria uma fora de ´pegar´ o nome/ip do cliente e não ´ler´ como fasso. mais valeu...
Usando o exemplo do meu último post, o servidor pega o IP e porta do cliente (nota: o cliente não enviou essas informações) automaticamente, o que fica faltando é descobrir o nome do cliente pelo IP, mas isso, se não me engano, tem alguns exemplo aqui no fórum.


Responder

24/03/2006

Paullsoftware

[quote:f9205494dc=´paullsoftware´]só que pensei que haveria uma fora de ´pegar´ o nome/ip do cliente e não ´ler´ como fasso. mais valeu...
Usando o exemplo do meu último post, o servidor pega o IP e porta do cliente (nota: o cliente não enviou essas informações) automaticamente, o que fica faltando é descobrir o nome do cliente pelo IP, mas isso, se não me engano, tem alguns exemplo aqui no fórum.[/quote:f9205494dc]
en entendi, até fiz um teste aqui e funcionou... vlw
[quote:f9205494dc=´paullsoftware´]o que fica faltando é descobrir o nome do cliente pelo IP, mas isso, se não me engano, tem alguns exemplo aqui no fórum.
[/quote:f9205494dc]
quanto a isso vou dar mais uma vasculhada pelo fórum :wink:


Responder

05/04/2006

Paullsoftware

op´s, ao invés de criar um novo Tópico resolvi resgatar esse para ficar tudo centralizado em um unico lugar...
toda vez que um cliente conecta ao sevidor eu jogo ele em uma lista (Listbox) e tb armazeno suas informações em [b:006f65b589]TThreadList[/b:006f65b589] até ai tudo bem, quando eu seleciono um cliente no listbox ele mostra as informações sobre ele como IP, tempo de acesso e outras informações...
O problema é que o meu ListBox está preparado para ser organizado em ordem alfabética e quando e quando o último cliente conecta ao servidor e esse fica sendo o primeiro da lista e dou um clique sobre ele aparece as informações sobre o primeiro cliente a ser conectado.
a pesquisa é feita assim hoje:
SelClient := pclient(Clients.LockList.Items[lbClients.ItemIndex]);

como faço para fazer essa pesquisa pelo no do item no listbox e não o índice?


Responder

Assista grátis a nossa aula inaugural

Assitir aula

Saiba por que programar é uma questão de
sobrevivência e como aprender sem riscos

Assistir agora

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar