Newsgroup: it.comp.lang.delphi
Titolo: TStream, Cardinal, Byte

Per metterne a fuoco l'uso in una comunicazione Client Server con i 
componenti Indy invio uno Stream "caricandolo" cosě:
mySize := 0;
for i := 0 to 3 do
begin
  myArray[i] := i;
  mySize := mySize + SizeOf(myArray[i]);
end;
DataSize := 4 * SizeOf(mySize);
IdTCPClient1.WriteCardinal(DataSize);
DataStream := TMemoryStream.Create;
for i := 0 to 3 do
  DataStream.WriteBuffer(myArray[i], SizeOf(myArray[i]);
IdTCPClient1.WriteStream(DataStream);
Se dichiaro l'array *myArray* come Cardinal, dal server leggo correttamente 
i valori ma se lo dichiaro come Array of Byte il server interrompe la 
lettura sulla riga
AThread.Connection.ReadStream(DataStream, DataSize)
E' possibile che il problema sia nel DataSize inviato precedentemente?
O se non č cosě mi sapete dare qualche indicazione?
Grazie
Valter

E' possibile che il problema sia nel DataSize inviato precedentemente?
Non calcolare la dimensione a mano, usa la proprietà Size dello
stream.  Ricordati che ogni scrittura su stream comporta che la
Position avanzi del numero di byte che scrivi, quindi prima di
ricominciare a usare lo stream (vedi spedirlo su socket), fa sì (anche
solo per sicurezza e null'altro) di riportare la Position a 0.

 solo per sicurezza e null'altro) di riportare la Position a 0.
ok, ma per scrupolo ho provato ad inviare i 4 byte (1-2-3-4) via stream
definendo il DataSize manualmente a partire da DataSize := 1 fino a DataSize
:= 24 ed ognuno dei valori non sono stati accettati dal server (definendo
l'array in byte, in smallint, in word). Non appena ho dichiarato l'array in
cardinal (con il DataSize corretto) il server ha risposto correttamente.
Nonj sarà che lo stream di Indy accetta solo numeri cardinal e non integer
(con tutti i suoi sottotipi)?
Altrimenti non mi spiego il comportamento.
Come ultimo tentativo porto la Position a 0 prima di inviare il tutto.
Tu che ne pensi, sbaglio io?
Valter

Come ultimo tentativo porto la Position a 0 prima di inviare il tutto.
Non dovrebbe essere strettamente necessario prima di una
WriteStream().  Assicurati, più che altro di quale sia l'endianess con
la quale il server riceve i dati.  I dati che passano su rete vengono
spediti seguendo il network byte order.  Per verificarlo, scrivi un
integer lato client e leggi byte per byte lato server facendo un dump
dei dati letti: analizzi quindi l'ordine dei byte e verifica se
l'endianess è corretto.

 l'endianess č corretto.
Per ora l'ho fatto su un array :-(
Per i dati in Cardinal la sequenza č corretta, per gli Integer, laddove ho
testato il DataSize manuale come ti ho detto da 1 a 24, o il server usciva
subito dopo la ReadStream (se non gli piaceva il DataSize) o terminava la
lettura dello stream ma solo il primo valore (1) era corretto...i tre
successivi erano sfalsati.

DataSize := 4 * SizeOf(mySize);
Questo calcolo è sbagliato, la moltiplicazione per 4 non serve.
Non c'è differenza tra DataSize e mySize.

 Non c'è differenza tra DataSize e mySize.
Accidenti, ora vado in confusione ;-)
In rete ho trovato due unit, client e server, da te postate e me le sto
rigirando in lungo ed in largo...la moltiplicazione in oggetto l'ho
carpita dal tuo codice :-)
n := random(5)+1
DataSize := n * SizeOf(n);
poi invii il DataSize al server come Cardinal
quindi crei uno stream
for i := 1 to n do
begin
  num := random(2000)+100;
  DataStream.WriteBuffer(num, SizeOf(num));
end;
quindi esegui il WriteStream
Ho notato che anche tu hai usato i cardinal quando bastavano delle
word, per questo ho pensato che lo stream non gestisse gli integer.
Per quanto riguarda la moltiplicazione, se la rimuovo ed il DataStream
= 4 i valori sono errati, se DataStream = 16 corretti.
Sto affogando qui dentro  :-)
Valter

 DataSize := n * SizeOf(n);
Questo significa: DataSize è uguale ad n volte la grandezza del tipo n,
che concettualmente, benché ambiguo, è giusto, nel senso che n e i valori
che vado a scrivere sono dello stesso tipo.  In realtà, la scrittura
corretta è:
DataSize := n * SizeOf(T); // con T qualsiasi tipo a piacere
...
for I := 1 to n do
 ... // scrivo n valori di tipo T
Come vedi, tutto quadra.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 IdTCPClient1.WriteStream(DataStream);
Dovresti usare DataStream.Write, non WriteBuffer
Giorgio 

 Dovresti usare DataStream.Write, non WriteBuffer
Nope.  E' WriteBuffer il metodo da usare.


Grazie a tutti i vostri suggerimenti infine sono arrivati i byte!
Usare WriteBuffer o Write all'interno del ciclo parrebbe però
ininfluente...con il DataSize e le variabili settati correttamente
l'array arriva come da invio...a naso mi parrebbe più corretto Write
dovendo scrivere dei valori sequenzialmente ma lavorano tutti e due...
Ciao
Grazie
Valter

 [...]più corretto Write
WriteBuffer si riduce a chiamare Write, dopo aver eseguito dei controlli.
E' WriteBuffer quella da usare...
