enviar um vetor, trabalhando com sockets

Delphi

18/05/2006

Olá pessoal, preciso de ajuda ok.

vamos ver se vocês conseguem me ajudar, o meu problema é o seguinte, tenho uma aplicação onde fica constantemente lendo alguns dados de um CLP(controlador logico progrmavel) estes dados me são retornados dentro de um vetor ok, ate ai perfeito o problema é o seguinte, quando um cliente se conectar a o meu servidor e mandar uma requisição de leitura, eu tenho que mandar esse vetor pra ele, ai é que esta o problema como mandar um vetor, ou se alguem tiver alguma outra ideia do que poderia fazer fico grato.
estou utilizando os componentes TClientSocket e TServerSocket, mandar um valor eu conigo,mas o vetor inteiro não..

bom aguardo dicas de vc´s ok

abraços.


Perdiga

Perdiga

Curtidas 0

Respostas

Perdiga

Perdiga

18/05/2006

e ai galera, ninguem tem alguma ideia.


GOSTEI 0
Kroki

Kroki

18/05/2006

Não entendí oque vc quer dizer com ´vetor´...


GOSTEI 0
Perdiga

Perdiga

18/05/2006

seguinte amigo vou tentar ser mais claro ok..

eu trabalho com Automação industrial e utilizo delphi para fazer meus supervisorios, ou seja tenho uma aplicação que fica lendo dento de um timer dados de um clp e esses dados são atribuidos a um vetor neste caso é um vetor de 30 posições ok... o que tenho que fazer é simples é passar esses dados que estão no vetor para o meu client para que ele mostre os dados na tela entendeu...

o que eu estou fazendo agora e me parece que não deu certo foi o seguinte quando meu cliente manda uma pergunta para o server que é o aplicativo onde esta fazendo esta leitura... no evento onRead do server eu fiz o seuinte

for i:=0 to 30 do
server.socket.conections[0].sendText(vetor[i]);

é isso que estou fazeno e no outro lado estou tentando remontar esse vetor.... mas o que percebi é que quando vai para o outro lado ele envia todos os dados de uma vez, so que com isso não consigo saber quais os dados nas suas posições..

não sei se você conseguiu me entender qualquer coisa é so falar.....


GOSTEI 0
Kroki

Kroki

18/05/2006

Não sei se isso te da uma luz porque uso Indy,mas tenho um aplicativo que le informações de tamanho variavel de um terminal.

...
IdTCPClient1.WriteLn(´unid´);//comando
while s <> ´fim´do begin
s:=IdTCPClient1.ReadLn;
ListBox1.Items.Append(s);
end;
IdTCPClient1.Disconnect;
Quando achado a string ´fim´ os dados estão todos no ListBox.
O programa Servidor envia o conteudo do memo;
...
for i:=0 to Memo1.Lines.Count-1 do begin
ASender.Thread.Connection.writeln(Memo1.Lines.Strings[i]);
end;
ASender.Thread.Connection.writeln(´fim´);
end;
...


GOSTEI 0
Thomaz_prg

Thomaz_prg

18/05/2006

Bom, agora não tenho como testar, mas vejo algumas formas de se fazer isso:

1. Criar um string que tenha todos os valores, onde os valores são delimitados. Por exemplo:
str := v1+´;´+v2+´;´+v3+´;´;
e daí para enviar:
server.socket.conections[0].sendText(str);
daí no cliente você só trataria a separação dos ítems.

2. Enviar uma variável do tipo Variant pelo SenBuf, onde essa variável seria o vetor. Tipo:
vvariant := VarArrayOf( [v1, v2, v3 ] );
para enviar:
server.socket.connections[0].sendbuf(vvariant);
no cliente, seria só passar o que foi recebido por ReceiveBuf para uma variável do tipo variant, e acessar diretamente os ítens:
vvariant[0], vvariant[1], etc....

Essas, creio eu, serem as mais simples de implementar.


GOSTEI 0
Perdiga

Perdiga

18/05/2006

poxa valeu amigos por essas dicas de vc´s, eu não tenho como testar elas aqui agora so segunda-feira, mas assim que testar posto se deu certo ou não ok.. muito obrigado mesmo galera.

Abraços.


GOSTEI 0
Perdiga

Perdiga

18/05/2006

ola Kroki.

Bom tentei do seu jeito, mas não da certo ele trava e não vai em frente.

olha o que fiz...

servidor.

for i:=0 to 30 do
MeuServidor.Socket.Connections[0].SendText(IntToStr(blcGeral[i]));
MeuServidor.Socket.Connections[0].SendText(´fim´);

e no cliente

i:=0;

msg:=Socket.ReceiveText;
while msg <> ´fim´ do
begin
ListBox1.Items.Append(msg);
inc(i);
end;


bom quando executo isso amigo, trava tudo........


quanto ao amigo thomaz_prg

acho que a primeira alternativa não seria a melhor entende... por ser um vetor de 30 posições que tenho, mas isso pode variar posso ter mais, então creio que não seje a melhor maneira, pelo motivo de ter que ficar passando posição a posição, em questão de 2 alternativa não entendi muito bem não se vc pudesse explicar com um pouco a mais de detalhes ficaria grato....


valeu..


GOSTEI 0
Perdiga

Perdiga

18/05/2006

galera olha so o que esta acontecendo, mudei um pouco as coisas..

no servidor criei um vetor para teste de 5 posições

no onRead tenho isso.

var
msg : string;
NumConex : integer;
begin
NumConex := Conexoes.IndexOf(Socket.Data);
if NumConex >= 0 then
msg := socket.ReceiveText; // pego a menssagem q chegou
if msg = ´R1´ Then
Leitura(NumConex);

o procedimento leitura faz isso..

var
i : integer;
begin
for i:=1 to 5 do
MeuServidor.Socket.Connections[NCon].SendText(IntToStr(vetor[i]));
end;


no cliente estou recebendo deste jeito.

begin
msg:=Socket.ReceiveText;
ListBox1.Items.add(msg);
end;

o que acontece é o seguinte tenho um botão enviar que tem o seguinte codigo
ListBox1.Clear;
If ClientSocket1.Active then
ClientSocket1.Socket.SendText(´R1´)
else
ShowMessage(´Voce não esta conectado com o servidor´);
end;

que envia uma requisição.

o que acontece é o seguinte na hora que mando enviar as vezes ele me devolve no meu listbox assim

ve vetor tenho os seguintes dados.
vetor[1]:= 2;
vetor[2]:= 50;
vetor[3]:= 3;
vetor[4]:= 5;
vetor[5]:= 6;

ai no Listbox as vezes vem correto que seria assim que deveria sempre aparecer
2
50
3
5
6
as vezes vem assim
250356
ou
2
50
356
e assim por diante ele não aparece sempre do mesmo jeito..


galera to apavorado preciso disso e não estou conseguindo

alguem tem alguma forma de se fazer isso..


valeu


GOSTEI 0
Thomaz_prg

Thomaz_prg

18/05/2006

Após a linha que tem o comando

MeuServidor.Socket.Connections[NCon].SendText(IntToStr(vetor[i]));

coloque uma espera:

Sleep(300);


GOSTEI 0
Perdiga

Perdiga

18/05/2006

não adianta não amigo..

infelizmente não funcionou..

mais alguma dica não faço a minima ideia do pq esteja acontecendo isso

teoricamente não deveria..

vou lhe falar uma coisa

quando coloquei um breakpoint no for que envia para o client

for i:=1 to 5 do
MeuServidor.Socket.Connections[NCon].SendText(IntToStr(vetor[i]));


ao invez de fazer na primeira passada i = 1, i = 2 e assim por diante, ele esta fazendo em ordem decrescente na primeira passada ele faz o seguinte

i = 5,i=4 e assim por diante, não sei se tem alguma coisa a ver mas so para comentar


abraço.


GOSTEI 0
Thomaz_prg

Thomaz_prg

18/05/2006

O seu código ficou assim???

for i:=1 to 5 do begin
MeuServidor.Socket.Connections[NCon].SendText(IntToStr(vetor[i])); 
sleep(300);
end; 






Se não funcionou assim, tente fazer da forma com a qual eu havia dito...

Da primeira forma, eu achei viável, pois ficaria assim (envio):

var 
  valor:string;
  i:integer;
begin
  valor := ´´;
  for i := 1 to 30 do   //Percorrer o vetor
    valor := valor + vetor[i] + ´;´ ;
  MeuServidor.Socket.Connections[NCon].SendText( valor );
end



Para receber:
var 
  valor, v :string;
  i:integer;
begin 
  valor := Socket.ReceiveText;
  i := 0 ; //posição inicial do vetor;
  while pos(´;´ , valor ) > 0 do begin 
    v := copy( valor , 1 , pos(´;´,valor)-1 );
    valor := copy( valor , pos(´;´,valor)+1 , length(valor) );
    vetor[i] := v;
    i := i + 1;
  end;
end;


Dessa forma, independente do tamanho do vetor, você poderia enviar ou receber os dados do vetor normalmente. Daria também para setar o tamanho do vetor em tempo de execução usando SetLength, e enviando, na primeira posição, o tamanho do vetor.


GOSTEI 0
Perdiga

Perdiga

18/05/2006

O seu código ficou assim???
for i:=1 to 5 do begin
MeuServidor.Socket.Connections[NCon].SendText(IntToStr(vetor[i])); 
sleep(300);
end; 
desculpa amigo, não tinha colocado o sleep dentro do begin não, agora eu testei e a principio funcionou. Se não funcionou assim, tente fazer da forma com a qual eu havia dito... Da primeira forma, eu achei viável, pois ficaria assim (envio):
var 
  valor:string;
  i:integer;
begin
  valor := ´´;
  for i := 1 to 30 do   //Percorrer o vetor
    valor := valor + vetor[i] + ´;´ ;
  MeuServidor.Socket.Connections[NCon].SendText( valor );
end
Para receber:
var 
  valor, v :string;
  i:integer;
begin 
  valor := Socket.ReceiveText;
  i := 0 ; //posição inicial do vetor;
  while pos(´;´ , valor ) > 0 do begin 
    v := copy( valor , 1 , pos(´;´,valor)-1 );
    valor := copy( valor , pos(´;´,valor)+1 , length(valor) );
    vetor[i] := v;
    i := i + 1;
  end;
end;
Dessa forma, independente do tamanho do vetor, você poderia enviar ou receber os dados do vetor normalmente. Daria também para setar o tamanho do vetor em tempo de execução usando SetLength, e enviando, na primeira posição, o tamanho do vetor.



bom, mas vou testar essa outra forma sua sim.... , já lhe digo se funcionou esta forma ok..

abração amigo e valeu por vc estar me ajudando.


GOSTEI 0
Perdiga

Perdiga

18/05/2006

blz amigão, parece que esse seu código, esta funcionando que é uma maravilha, nos testes, agora vamos ter que colocar ele funcionando para ver se vai continuar legal..... ficou bem melho que colocar um sleep. é pq eu vou fazer uma leitura a cada 1s e mais de um cliente pode estar fazendo entende, por isso necessito de melhor performace..

mas acredito que com esse seu codigo va funcionar legal, não tinha pensado nisso ainda amigo, quando voçê deu a sujestão imaginava outra coisa... principiante no mundo da programação é isso mesmo né amigo, mas um dia chego lá ainda mais com ajuda que estou tendo do pessoal..


valeu mesmo e abraço eim, qualquer coisa vou voltar a postar aqui para dizer se funcionou legal..
fiz os testes enviando um vetor de apenas 5 posições, vamos ver depois ok..

mais uma vez obrigado.


GOSTEI 0
POSTAR