Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

how write stream from TCPClient to TCPServer?

127 views
Skip to first unread message

Felipe Molina

unread,
Jun 1, 2001, 3:50:41 AM6/1/01
to
Hi all

I'm need send a strem from TCPClient to TCPServer,
Try this but don't work:

Server side;

with AThread.Connection do begin
sCommand := ReadLn;
if SameText(cOPY(sCommand, 1, 6), 'UPLOAD') then begin
stream:=Tmemorystream.create;
ReadStream(stream);
stream.SaveToFile(filename);
stream.free; end;

Client side:

stream:=TmemoryStream.create;
IdTCPClient1.host:=Ehostname.text;
IdTCPClient1.connect;
memo1.clear;
Try
Memo1.lines.Add(IdTCPClient1.ReadLn);
IdTCPClient1.writeLn('UPLOAD'+FilenameEdit1.TEXT);
while IdTCPClient1.connected do
begin
IdTCPClient1.OpenWriteBuffer;
IdTCPClient1.WriteStream(stream);
IdTCPClient1.CloseWriteBuffer;
stream.free;
IdTCPClient1.disconect;


thanks in advance


Bruno Lovatti

unread,
Jun 1, 2001, 8:16:09 AM6/1/01
to
There are examples in the demos.
ImageServer
And more.

Bruno


Felipe Molina

unread,
Jun 1, 2001, 8:17:19 AM6/1/01
to

"Bruno Lovatti" <blov...@vix.zaz.com.br> escribió en el mensaje
news:3b178729_1@dnews...

The example show how send a stream from server to client, I need make
contrary, send stream from client to server.

thanks


Bruno Lovatti

unread,
Jun 1, 2001, 10:38:16 AM6/1/01
to
I send like this from client to server:

sending a stringlist from the client

sl is TStringList
ms is TMemoryStream
comando is integer
sRetorno is string
ID_PROCESSAR is one of my consts

// Enviar o que foi processado
if sl.count > 0 then begin
ms := TMemoryStream.Create;
sl.SaveToStream( ms );
FreeAndNil(sl);
TCPClient.WriteLn( FormatFloat('00',ID_PROCESSA_SIZE) +
IntToStr(ms.size) );
sRetorno := TCPCLient.ReadLn;
comando := StrToInt( copy(sRetorno,1,2) );
sRetorno := copy(sRetorno,3,length(sRetorno)-2);
if comando = ID_PROCESSAR then begin
ms.position := 0;
TCPClient.OpenWriteBuffer;
TCPClient.WriteStream(ms);
TCPClient.CloseWriteBuffer;
end;
FreeAndNil(ms);
end;


at server side

str is string
comando and Processa_Size are integer
ID_PROCESSA_SIZE and ID_PROCESSAR are consts

str := uppercase(AThread.Connection.ReadLn);
comando := StrToInt(copy(str,1,2));
str := copy(str,3,length(str)-2);
case comando of
ID_PROCESSA_SIZE:
begin
try
Processa_Size := StrToInt(str);
except
Processa_Size := 0;
end;
if Processa_Size > 0 then begin
AThread.Connection.WriteLn( FormatFloat('00',ID_PROCESSAR) );
if ms <> nil then FreeAndNil(ms);
ms := TMemoryStream.Create;
AThread.Connection.ReadStream(ms,Processa_Size,false);
sl := TStringList.Create;
ms.position := 0;
sl.LoadFromStream(ms);
FreeAndNil(ms);
ProcessarEmprestimosPendentes(sl); // My function, you don't need
FreeAndNil(sl);
end;
end;
end;


Bruno
Sorry for english mistakes!


Bruno Lovatti

unread,
Jun 1, 2001, 10:40:15 AM6/1/01
to
at server side

the code is in event

procedure TfMain.TCPServerExecute(AThread: TIdPeerThread);

Bruno


R. Brian Lindahl

unread,
Jun 1, 2001, 10:40:34 AM6/1/01
to
See comments in your code below...

"Felipe Molina" <cre...@terra.es> wrote in message news:3b174954_2@dnews...


> Server side;
>
> with AThread.Connection do begin
> sCommand := ReadLn;
> if SameText(cOPY(sCommand, 1, 6), 'UPLOAD') then begin

> //stream:=Tmemorystream.create;
stream := tfilestream.create(filename,fmCreate);
> ReadStream(stream);
> //stream.SaveToFile(filename);


> stream.free; end;
>
> Client side:
>
> stream:=TmemoryStream.create;
> IdTCPClient1.host:=Ehostname.text;
> IdTCPClient1.connect;
> memo1.clear;
> Try
> Memo1.lines.Add(IdTCPClient1.ReadLn);
> IdTCPClient1.writeLn('UPLOAD'+FilenameEdit1.TEXT);
> while IdTCPClient1.connected do
> begin
> IdTCPClient1.OpenWriteBuffer;

> //IdTCPClient1.WriteStream(stream);
IdTCPClient1.WriteStream(stream,true,true);
> IdTCPClient1.CloseWriteBuffer;
> stream.free;
> IdTCPClient1.disconect;
>

Two changes -

1. you don't need to use a TMemoryStream on the server - that will eat up a
bunch of memory every time you transfer a file.

2. By default, the ReadStream function assumes that there is a byte count
included in the stream. However, the default for WriteStream doesn't include
this byte count. You have to use the (...,true,true) parameters to get this
to happen.

Comments

- I don't usually use the OpenWriteBuffer/CloseWriteBuffer methods. Without
them, it is my understanding that the data is sent as the various WriteXXX
methods are called. In this case, since you are sending a stream, it can go
all at once anyway. Especially since as written, there is a memory
allocation equal to the size of the stream you are sending. Depending on the
client machine, this may or may not be significant. I try to make as few
demands on client-side RAM as possible in this kind of situation.

- I assume you are filling the TMemoryStream on the client with some data
before you send it. If you are loading it from a file, it is more efficient
to use a TFileStream as in change #1, above.

HTH...

brian


Ernst Gerlach

unread,
Jun 1, 2001, 3:00:11 PM6/1/01
to
"Felipe Molina" <cre...@terra.es> schrieb im Newsbeitrag
news:3b1787d3_2@dnews...
Client side, its a printer driver, witch sends the faxfiles to the server:
----------------------
with GFaxClient do begin
Port := GFax_Port;
Host := SH12_Ed_DomainAdresse.Text;
try
Connect;
SH5_MemoLog.Lines.Add('Faxer mit Server verbunden');
except
if Connected then Disconnect;
SH5_MemoLog.Lines.Add('TCP/IP-Fehler');
end;
If Connected then begin
STempR := ReadLnWait;
WriteLn('CLIENTF');
STempR := ReadLnWait;
WriteLn('AAAAAAA');
STempR := ReadLnWait;
WriteLn('ABSENDR ' + SH12_Ed_meinName.Text + '@'
+ SH12_Ed_DomainName.Text);
WriteLn('KENNUNG ' + SH6_Ed_FaxID.Text);
WriteLn('KOPFNAM ' + SH6_Ed_FaxKennung.Text);
WriteLn('ANZAHL1 1');
WriteLn('PRIORI: 1'); // Option future
WriteLn('FNUMMER ' + STemp1);
WriteLn('FILENAM ' + ExtractFileName(APFName));
DerStream := TMemoryStream.Create;
try
DerStream.LoadFromFile(APFName);
DerStream.Seek(0, soFromBeginning);
WriteStream(DerStream, true, true);
finally
DerStream.Free;
end;
STempR := ReadLnWait;
Disconnect;
DeleteFile(APFName);
DeleteFile(APXName);
SH5_MemoLog.Lines.Add('FaxMail gesendet ID '
+ IntTostr(DieIDX));
end; { if Connected }
end; { with Client }
------------------------
The server (receives from printerdriver and send to faxprogram):
---------------------
procedure TFm_Server.EG_FaxServerExecute(AThread: TIdPeerThread);
var
FData : TFaxData;


procedure FaxSucheDateiName;
var
IstDa : boolean;
IstNummer : integer;
begin
IstDa := true; IstNummer := 1;
while IstDa do begin
FData.APFDateiName := Faxverzeichnis
+ '\' + FormatDateTime('yymmdd"_"hhnnss', now)
+ IntToStr(IstNummer) + '.APF';
IstDa := FileExists(FData.APFDateiName);
inc(IstNummer);
end;
FData.APXDateiName := ChangeFileExt(FData.APFDateiName, '.APX');
end;

{ ------------------- Einzelbefehle ------------------- }


procedure FaxStop;
begin
FData.Beenden := true;
FData.BefehlsNummer := 0;
end;

procedure FaxFehler;
begin
AThread.Connection.WriteLn('STOP');
FData.Beenden := true;
FData.BefehlsNummer := 0;
end;

procedure FaxClientStart;
begin
AThread.Connection.WriteLn('TRUE');
if FData.CliPhase = 0 then FData.CliPhase := 1
else FaxFehler;
FData.BefehlsNummer := 0;
end;

procedure FaxClientReply;
begin
AThread.Connection.WriteLn('FALSE');
if FData.CliPhase = 1 then FData.CliPhase := 2
else FaxFehler;
FData.BefehlsNummer := 0;
end;

procedure FaxFileNameXX;
begin

FData.FaxInfo.Add('FILENAM ' + FData.EmpfangString);
if FData.CliPhase = 2 then FData.CliPhase := 3
else FaxFehler;
FData.DerPuffer := TMemoryStream.Create;
try
AThread.Connection.ReadStream(FData.DerPuffer);
FaxSucheDateiName;
FData.DerPuffer.SaveToFile(FData.APFDateiName);
FData.FaxInfo.SaveToFile(FData.APXDateiName);
finally
FData.DerPuffer.Free;
FData.DerPuffer := NIL;
AThread.Connection.WriteLn('OK');
end;
FData.Beenden := true;
FData.BefehlsNummer := 0;
end;

procedure FaxAbsender;
begin
FData.FaxInfo.Add('ABSENDR ' + FData.EmpfangString);
FData.BefehlsNummer := 0;
end;

procedure FaxFNummer;
begin
FData.FaxInfo.Add('FNUMMER ' + FData.EmpfangString);
FData.BefehlsNummer := 0;
end;

procedure FaxKennung;
begin
FData.FaxInfo.Add('KENNUNG ' + FData.EmpfangString);
FData.BefehlsNummer := 0;
end;

procedure FaxKopfName;
begin
FData.FaxInfo.Add('KOPFNAM ' + FData.EmpfangString);
FData.BefehlsNummer := 0;
end;

procedure FaxAnzahl1;
begin
FData.FaxInfo.Add('ANZAHL1 ' + FData.EmpfangString);
FData.BefehlsNummer := 0;
end;

procedure FaxRHeader;
begin
FData.FaxInfo.Add('HEADER ' + FData.EmpfangString);
FData.BefehlsNummer := 0;
end;

procedure FaxPriori;
begin
FData.FaxInfo.Add('PRIORI ' + FData.EmpfangString);
FData.BefehlsNummer := 0;
end;

procedure FaxRunServer;
var
Gefunden : integer;
SuchRec : TSearchRec;
Fehler : Boolean;
begin
Fehler := false;
Gefunden := FindFirst(Faxverzeichnis + '*.APX', faAnyFile, SuchRec);
while (Gefunden = 0) and (SuchRec.Size > 0) do begin
FData.APXDateiName := Faxverzeichnis + SuchRec.Name;
FData.APFDateiName := ChangeFileExt(FData.APXDateiName, '.APF');
AThread.Connection.WriteLn('FILE');
FData.DerPuffer := TMemoryStream.Create;
try
FData.DerPuffer.LoadFromFile(FData.APXDateiName);
FData.DerPuffer.Seek(0, soFromBeginning);
try
AThread.Connection.WriteStream(FData.DerPuffer, true, true);
except
Fehler := true;
end;
FData.DerPuffer.Clear;
FData.DerPuffer.LoadFromFile(FData.APFDateiName);
FData.DerPuffer.Seek(0, soFromBeginning);
try
AThread.Connection.WriteStream(FData.DerPuffer, true, true);
except
Fehler := true;
end;
if not Fehler then begin
DeleteFile(FData.APXDateiName);
DeleteFile(FData.APFDateiName);
end;
finally
FData.DerPuffer.Free;
FData.DerPuffer := NIL;
end;
Gefunden := FindNext(SuchRec);
end;
if not Fehler then AThread.Connection.WriteLn('OK')
else AThread.Connection.WriteLn('ERR');
FData.Beenden := true;
FData.BefehlsNummer := 0;
end;


procedure ProcessFax;
begin
if FData.BefehlsNummer = 0 then begin
FData.Befehl := Fetch(FData.EmpfangString, ' ');
if FData.Befehl = 'CLIENTF' then FData.BefehlsNummer := 1 else
if FData.Befehl = 'AAAAAAA' then FData.BefehlsNummer := 2 else
if FData.Befehl = 'FILENAM' then FData.BefehlsNummer := 3 else
if FData.Befehl = 'ABSENDR' then FData.BefehlsNummer := 4 else
if FData.Befehl = 'FNUMMER' then FData.BefehlsNummer := 5 else
if FData.Befehl = 'KENNUNG' then FData.BefehlsNummer := 6 else
if FData.Befehl = 'KOPFNAM' then FData.BefehlsNummer := 7 else
if FData.Befehl = 'ANZAHL1' then FData.BefehlsNummer := 8 else
if FData.Befehl = 'HEADER:' then FData.BefehlsNummer := 9 else
if FData.Befehl = 'PRIORI:' then FData.BefehlsNummer := 10 else
if FData.Befehl = 'SERVER' then FData.BefehlsNummer := 101 else
//if FData.Befehl = 'CLIENT' then FData.BefehlsNummer := 1 else

if FData.Befehl = 'STOP' then FData.BefehlsNummer := 998 else
FData.BefehlsNummer := 999;
end; { if FData.BefehlsNummer = 0 }
(* LoggSektion.Enter; { ------ Block -------- } //only for debug
Fm_Haupt.DerLogText := FData.Befehl + IntToStr(FData.BefehlsNummer);
//only for debug
AThread.Synchronize(Fm_Haupt.SchreibeLog); //only for debug
LoggSektion.Leave; { ------ Block -------- } //only for debug *)
case FData.BefehlsNummer of
1 : FaxClientStart;
2 : FaxClientReply;
3 : FaxFileNameXX;
4 : FaxAbsender;
5 : FaxFNummer;
6 : FaxKennung;
7 : FaxKopfName;
8 : FaxAnzahl1;
9 : FaxRHeader;
10 : FaxPriori;
101 : FaxRunServer;
998 : FaxStop;
999 : FaxFehler;
else FaxFehler;
end; { case FData.BefehlsNummer of }
end; { procedure ProcessFax }

begin { ------------------- Execute ------------------- }
FData := Pointer(AThread.Data);
try
FData.BefehlsNummer := 0;
FData.CliPhase := 0;
FData.SerPhase := 0;
FData.TimeOutCount := 0;
FData.Beenden := false;
AThread.Connection.WriteLn('START');
while AThread.Connection.Connected and (not FData.Beenden)
and (FData.TimeOutCount <= 60) do begin
FData.EmpfangString := AThread.Connection.ReadLn('', 1000);
if (not AThread.Connection.ReadLnTimedOut) then begin
FData.TimeOutCount := 0;
(* LoggSektion.Enter; { ------ Block -------- } //only for debug
Fm_Haupt.DerLogText := FData.EmpfangString; //only for debug
AThread.Synchronize(Fm_Haupt.SchreibeLog); //only for debug
LoggSektion.Leave; { ------ Block -------- } //only for debug *)
ProcessFax;
end else FData.TimeOutCount := FData.TimeOutCount + 1;
end;
finally
if AThread.Connection.Connected
then AThread.Connection.Disconnect;
end;
end;


procedure TFm_Server.EG_FaxServerConnect(AThread: TIdPeerThread);
var
FData : TFaxData;
begin
FData := TFaxData.Create;
AThread.Data := FData;
FData.FaxInfo := TStringList.Create;
end;

procedure TFm_Server.EG_FaxServerDisconnect(AThread: TIdPeerThread);
var
FData : TFaxData;
begin
FData := Pointer(AThread.Data);
if FData.FaxInfo <> NIL then begin
FData.FaxInfo.Free;
FData.FaxInfo := NIL;
end;
if FData.DerPuffer <> NIL then begin
FData.DerPuffer.Free;
FData.DerPuffer := NIL;
end;
FData.Free;
AThread.Data := nil;
end;
---------------------

--

Ernst Gerlach
ernst....@epost.de
http://www.gerlach-mtl.de
--- use plain text only in email ---


Brandon Smith

unread,
Jun 1, 2001, 11:16:20 PM6/1/01
to
I send streams both ways, and at first mine didn't work either. I finally
realized you have to reset the stream position to zero inbetween each
manipulation:

Mystream.readFromWhatever;
// at this point the stream's position is the same as it's size
// and if you try to write it somewhere, either to a socket or to a file,
nothing will happen,
// since writing assumes you are starting at the current position and going
to the end.
// so you need this:
Mystream.position := 0;
// now the stream is ready for the next thing
Client.sendstream or athread.connection.readstream

HTH

Brandon

"Felipe Molina" <cre...@terra.es> wrote in message news:3b174954_2@dnews...

0 new messages