Fórum Programinha pra verificar a conexao em rede #299897

19/10/2005

0

Preciso fazer um programinha bem simples, e precisaria de umas idéias.

Preciso fazer um programinha assim:
numa máquina ficará um servidor, pode ser idTCP ou qualquer outro
na outra máquina ficará um client, pode ser idTCP ou qualquer outro.

quero saber quantas vezes por dia o cliente perde conexão com o server, então, se o cabo for desconectado, o server for desligado, um problem de tráfego, virus etc me desconectar ou o próprio Satanás soprar os cabos da Telefônica eu gostaria que aparecessa na tela do client uma messagebox (´se ferrou mané´);

fiz uma usando idTCPserver e client, mas ficou meio porco porque:

1) depois do client conectado, ele não percebe que foi desconectado, só se tentar enviar um dado ou tentar conectar de novo, e eu não vou colocar um timer pra ficar fazendo isso.

2) uma máquina pode estar conectada na rede, mas o idTCP pode não saber ou não se conectar se a configuração da máquina só permitir conexão icmp, udp etc (se bem que isso não é problema, já que eu quero monitorar só o tcp)

não sei como fazer tipo um ping em delphi.


valew!


Vitor Rubio

Vitor Rubio

Responder

Posts

19/10/2005

Massuda

[quote:02ab67e090=´vitor^_^´]1) depois do client conectado, ele não percebe que foi desconectado, só se tentar enviar um dado...[/quote:02ab67e090]Infelizmente, esse é o modo de funcionamento do TCP... você só percebe que está desconectado se tentar comunicar com o servidor (e vice versa).

O que você pode fazer é enviar periodicamente algo do cliente para o servidor (isso é o PING) ou mandar algo do servidor para o cliente (geralmente isso se chama KEEP ALIVE); o PING é mais fácil de fazer.

No cliente, coloque um timer e periodicamente envie o PING para o servidor; faça o servidor responder algo útil (costuma-se por algo relacionado com tempo, assim dá para medir quanto tempo demora para ir do cliente para o servidor).

[quote:02ab67e090=´vitor^_^´]... eu não vou colocar um timer pra ficar fazendo isso.[/quote:02ab67e090]Não sei como faria sem um timer.


Responder

Gostei + 0

19/10/2005

Vitor Rubio

Beleza, digamos que vamos fazer com timer mesmo.
Eu envio um comando ou mensagem do client pro server, mas eu não sei como fazer pro server responder, nem como pegar essa resposta no client. Alem disso, mesmo com o server desativado, a máquina ainda pode estar na rede....


Responder

Gostei + 0

19/10/2005

Massuda

[quote:e2a81af454=´vitor^_^´]...não sei como fazer pro server responder, nem como pegar essa resposta no client.[/quote:e2a81af454]O jeito mais fácil é fazer o cliente enviar algo simples, por exemplo, ´PING´.

No TidTCPServer, no Object Inspector, selecione a propriedade CommandHandlers e dê um clique duplo (ou clique no botão com ...); clique no botão ´Add new´. No Object Inspector, na propriedade Command, digite PING e na propriedade Response dê um clique duplo (ou clique no botão com ...) e digite OK. Isso deve ser suficiente se você não criou um (tratador de) evento para o evento OnExecute do servidor.

[quote:e2a81af454=´vitor^_^´]...Alem disso, mesmo com o server desativado, a máquina ainda pode estar na rede....[/quote:e2a81af454]Concordo, com isso, mas acho que aí o problema seria outro, também ´fácil´ de resolver. O problema seria garantir que o servidor está sempre rodando. Nesse caso, você pode fazer algo como oIBGuardian do Interbase, que é um programa que checa se o servidor IB está rodando e, se ele não estiver, ele iniciar o servidor. Ou você está pensando em algo diferente?


Responder

Gostei + 0

19/10/2005

Vitor Rubio

Não, eu posso fazer desse jeito mesmo, o que eu preciso não é tão sofisticado assim, eu estou fazendo a conexão pela porta 6666, que eu escolhi aleatoreamente.
Apenas, se fosse possivel saber se a máquina do servidor está conectada, por qualquer protocolo ou porta (tipo pingar ele) eu gostaria de aprender como.

Com relação ´PING´, beleza, o idTCPServer vai me responder ´OK´, mas como eu pego esse ´OK´ no meu client? tem q dar readln no server?


Responder

Gostei + 0

19/10/2005

Massuda

[quote:14ea743414=´vitor^_^´]...como eu pego esse ´OK´ no meu client? tem q dar readln no server?[/quote:14ea743414]O jeito mais simples é dar um WriteLn seguido de um ReadLn no cliente. Se a conexão tiver sido terminada, o WriteLn falhará; se não tiver resposta (defina um valor razoável de timeout), algo muito ruim aconteceu no seu servidor.


Responder

Gostei + 0

19/10/2005

Vitor Rubio

se o writeln falhar, é porque tá desconectado, se não tiver resposta, é porque o programa server não está funcionando! beleza, isso resolve!


Valeu Massuda!


Responder

Gostei + 0

21/10/2005

Vitor Rubio

Aí massuda, outra dúvida:

criei um comandinho ´snap´ que quando eu mando para o server, o server faz um snapshot da sua tela atual, joga num bitmap e depois joga numa memory stream.

como eu faço pra passar essa stream do servidor pro cliente?


Assim eu poderia visualizar numa form...



Valew!


Responder

Gostei + 0

21/10/2005

Massuda

[quote:f92bc1dc0b=´vitor^_^´]como eu faço pra passar essa stream do servidor pro cliente?[/quote:f92bc1dc0b]Na conexão, além do WriteLn/ReadLn tem um WriteStream/ReadStream. Na hora de enviar faça algo assim...
SuaStream.Position := 0; // posiciona no início
SuaConexão.WriteInteger(SuaStream.Size);
SuaConexão.WriteStream(SuaStream);
...e na hora de ler...
var
  Size: Integer;
...
  Size := SuaConexão.ReadInteger;
  SuaConexão.ReadStream(SuaStream, Size);



Responder

Gostei + 0

31/10/2005

Vitor Rubio

Massuda, eu testei aquilo que você falou, mas não deu certo:
primeiro porque o server não tem os métodos writeinteger e writestream, então eu tive que adicionar um client no programa servidor pra escrever os dados no proprio server. (acho que isso deve ser normal)

Depois disso, ao usar o client para escrever a stream no server, ocorre uma exception dizendo que foi excedido o número máximo de linhas que pode ser enviado. Não adianta eu setar a propriedade maxlinelength pra 0 ou -1, continua com o mesmo erro. (alem disso eu acho que essa propriedade é o tamanho maximo de uma linha, e não omaximo de linhas)

Continuo sem saber como enviar e receber um stream. meu stream não é muito grande, o número de bytes não chega nem perto de exceder o limite de um integer. Aliás, ele tem uns 50000 bytes no máximo.


Obrigado pela força! ^^


Responder

Gostei + 0

01/11/2005

Firekiller

Sei que se o que vou dizer, seria meio que pedir pra se retroagir, mas, lá vai... Se você estiver usando CLientSocket e ServerSockert (palheta Internet), você envia o stream, assim ServerSocket.Socket.SendStream() ou então use SendBuf(). Para recebê-lo, coloque assim no evento OnRead do ClientSocket (ou ClientRead do ServerSocket)

var
s:TMemoryStream;
b:String;
i:Integer;

s := TMemorySTream.create;
i := Socket.ReceiveLength;
while i > 0 do begin
Socket.ReceiveBuf( b , i);
s.WriteBuf( b , length(b) );
sleep(200);
i := Socket.ReceiveLength;
end;


Estes componentes são mais simples para se trabalhar (pelo menos na minha opinião), porém já estão deixados de lado... atualmente utiliza-se os da palheta Indy mesmo (os que você está usando), porém eu acho eles mais complicados.


Responder

Gostei + 0

01/11/2005

Vitor Rubio

Eh... nem tudo que é novo é melhor ou mais útil só porque é novo.... mas esses componentes que você citou eu nunca usei na minha vida ... e como todas as outras funcionalidades do programa estão prontas, so faltava essa, seria meio dificil migrar de componentes agora. Vou ver se alguem sabe mandar e receber streams usando indy, se não aparecer ninguem, vou tentar migrar tudo o que eu já fiz do jeito que você explicou.

Obrigado pela ajuda :wink:


Responder

Gostei + 0

01/11/2005

Massuda

Não testei, mas isso deve transferir uma stream do servidor para o cliente...
// no comando SNAP do servidor
procedure TForm1.IdTCPServer1CmdSnapCommand(ASender: TIdCommand);
var
  Stream: TMemoryStream;
begin
  Stream := TMemoryStream.Create;
  try
    // gera um bitmap e copia para Stream

    Stream.Position := 0; // posiciona no início
    ASender.Thread.Connection.WriteInteger(Stream.Size);
    ASender.Thread.Connection.WriteStream(Stream);
  finally
    Stream.Free;
  end;
end;

// no cliente

procedure TForm2.PedeSnapshot(var ASnapshot: TBitmap);
var
  Stream: TMemoryStream;
  Size: Integer;
begin
  Stream := TMemoryStream.Create;
  try
    IdTCPClient1.Writeln(´SNAP´);
    Size := IdTCPClient1.ReadInteger;
    IdTCPClient1.ReadStream(Stream, Size);

    // copia o bitmap da Stream
  finally
    Stream.Free;  
  free;
end;



Responder

Gostei + 0

03/11/2005

Vitor Rubio

Massuda, eu acho que esse código até deve funcionar, mas o problema é o seguinte: o meu cliente fica ´conversando´ com o servidor, sempre mandando o comando ping e recebendo de volta a string ´ok´+ a hora.

Quando eu paro a execução dos 2 timers (cliente e servidor) ainda tem um monte de strings ´ok´ na fila. Se eu sou um writeinteger no servidor, ele entra depois desses ´ok´. Se eu dou um readinteger no cliente, ele vai tentar transformar esses 8 bytes te texto num número, transsformando assim num número esdrúxulo e uma stream errada.

precisaria saber como se limpa as linhas do server.

mas estamos quase conseguindo ^^


Responder

Gostei + 0

03/11/2005

Massuda

[quote:398fe5ff32=´vitor^_^´]o meu cliente fica ´conversando´ com o servidor, sempre mandando o comando ping e recebendo de volta a string ´ok´+ a hora. Quando eu paro a execução dos 2 timers (cliente e servidor) ainda tem um monte de strings ´ok´ na fila.[/quote:398fe5ff32]com que frequencia você manda o ping? Porque tem 2 timers?


Responder

Gostei + 0

04/11/2005

Vitor Rubio

Conseguiiiiiiii Massudaaa!!!

Eu nem expliquei direito como que o programa funcionava, seguinte:

Tenho um banco de dados interbase num servidor que todo mundo (as outras máquinas) conhecem e sabem onde está. Tem uma tabela nesse banco que meu programinha server fica gravando o endereço IP dele a cada 30 minutos (isso porque o ip pode mudar quando a máquina for reiniciada, é dinamico). É por isso que tem timer no server também. Nada haver né? Aliás, esqueci de falar, ambos, tanto o client como o server iniciam junto com o windows, porque eu criei uma entrada lá no run do registro.

A cada 2 segundos o cliente ´pinga´ o server, se não conseguir conexão, ele verifica na tabela do banco de dados interbase se o IP não mudou, se mudou ele pega o novo, se mesmo assim ele não conseguir conectar ele desiste. Ah, antes de pingar a primeira vez ele verifica qual é o primeiro ip que tá lá né? (dãn).

Bom, eu consegui mandar e ler a stream fazendo uma gambiarra. Eu poderia usar um outro server em outra porta pra isso, e outro client, mas o que eu fiz: Quando eu congelo os 2 timers, eu dou um write(´|´) no server (não writeln). No cliente eu dou um readln(´|´). Ou seja, como o novo terminador é ´|´ ao invés de #13, ele vai ler todos os bytes até encontrar o ´|´, inclusive ele mesmo. O único problema é se minha stream contiver um ´|´ também.... mas aí é muita sacanagem do murphy hauahau.

Depois de mandar/receber os streams, eu mando/recebo um ´|´ de novo, pra zerar tudo, e reativo os timers.

Antes de mandar o stream eu compacto o stream usando a zlib, pra ficar mais levinho, (tcompressionstream etc...) depois descompacto na hora que receber, pra mostrar.

Consegui fazer o snapshot e até ´filmar´ a tela do server, fazendo snapshots consecutivos a cada 15 milissegundos.... Funcionou durante alguns minutos... mas ficou pesadão e lentão... mas não importa, aos poucos agente vai melhorando, já ficou muito melhor com a zlb do que sem heheheeh. Será que eu consigo fazer um VNC? O meu objetivo nem era esse, o meu objetivo na verdade era criar um programa que pudesse mandar imagens de uma camera do server pra minha casa, tipo pra vigilância...


Bom... será que é interessante eu postar o código fonte dele inteiro aki? Ele tem bastante exemplos interessantes de como se usam certas coisas, que eu usei pela primeira vez, como TidTcpserver/client e zlib.

Valeu pela força que vc me deu!


Responder

Gostei + 0

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

Aceitar