Board index » delphi » Indy TCP Client / Server WriteFile Problem

Indy TCP Client / Server WriteFile Problem

Hi All,

This may seem like a really silly question, but here goes. I am trying
to transfer 2 or more files using the idTCPClient "WriteFile" method.
The problem I am facing is that only the first file is sent. I do not
get an error but the subsequent files are not transferred. Here is a
portion of my code:

for i := 0 to frmMain.listbox1.items.count - 1 do
begin
    try
       IdTCPClient1.WriteLn('FILE');
       IdTCPClient1.WriteFile(frmMain.listbox1.items[i]);
    except
       on E: Exception do Showmessage(E.Message);
    end;
end;

It does not appear to be a problem on the server end (which reads the
command "FILE" and then received the file) because the first file comes
through 100% ok, it just skips the remaining files.

Any thoughts would be appreciated :-)

Thanks!
Dominik.

 

Re:Indy TCP Client / Server WriteFile Problem


Quote
"Dominik Moreitz" <dmore...@remove.hotmail.com> wrote in message

news:3ee82e3b$1@newsgroups.borland.com...

Quote
> Here is a portion of my code:

What does your actual receiving code look like?  Is it explitically looking
for "FILE" each time or are you just reading the socket endlessly?
WriteFile() does not delimit the file data in any way, and it does not send
the file's actual size, either.  So you have to handle all of that yourself
manually.  Otherwise, I would suspect that your receiving code is actually
receiving all of the data for all of the files correctly, but since it can't
know how much data actually belongs to which files, it just dumps everything
into a single file only.  But, without seeing the rest of your code, it is
hard to diagnose your actual problem.  Please show a more complete code
snippet.

Gambit

Re:Indy TCP Client / Server WriteFile Problem


Hi!

You are absolutely right. I sent 1 hlp and 2 txt files, and the
resulting hlp file was as big as all 3 put together. I did not spot this
because the help file opens perfectly (which is even more bizarre).

Snippet of server code:

if sCommand = 'FILE' then
begin
    t1 := AThread.Connection.Readln;
    ftmpStream := TFileStream.Create(workpath+'\'+t1,fmCreate);
    while AThread.Connection.Connected do
       AThread.Connection.ReadStream(fTmpStream,-1,true);
    FreeAndNil(fTmpStream);
end;

I am not sure how to tell the server a new file is coming. I am sending
the "FILE" command ahead of every single file. I have looked at the help
but am still not sure.

Thanks for your help!!

Regards,
Dominik.

Quote
Remy Lebeau (TeamB) wrote:
> "Dominik Moreitz" <dmore...@remove.hotmail.com> wrote in message
> news:3ee82e3b$1@newsgroups.borland.com...

>>Here is a portion of my code:

> What does your actual receiving code look like?  Is it explitically looking
> for "FILE" each time or are you just reading the socket endlessly?
> WriteFile() does not delimit the file data in any way, and it does not send
> the file's actual size, either.  So you have to handle all of that yourself
> manually.  Otherwise, I would suspect that your receiving code is actually
> receiving all of the data for all of the files correctly, but since it can't
> know how much data actually belongs to which files, it just dumps everything
> into a single file only.  But, without seeing the rest of your code, it is
> hard to diagnose your actual problem.  Please show a more complete code
> snippet.

> Gambit

Re:Indy TCP Client / Server WriteFile Problem


Quote
"Dominik Moreitz" <dmore...@remove.hotmail.com> wrote in message

news:3ee91a52$1@newsgroups.borland.com...

Quote
> You are absolutely right. I sent 1 hlp and 2 txt files,
> and the resulting hlp file was as big as all 3 put
> together. I did not spot this because the help file
> opens perfectly (which is even more bizarre).

That is because the first part of the saved file contained correct HLP data,
and everything is relative to the beginning of the file, so there was no
reason for the Help system to complain, everything was located where it was
supposed to be.  Had you transmitted a different file first, then it would
have blown up on you instead.

Quote
> if sCommand = 'FILE' then
> begin
>     t1 := AThread.Connection.Readln;
>     ftmpStream := TFileStream.Create(workpath+'\'+t1,fmCreate);
>     while AThread.Connection.Connected do
>        AThread.Connection.ReadStream(fTmpStream,-1,true);
>     FreeAndNil(fTmpStream);
> end;

Yup, you're reading all of the files into the same storage file on the
receiving end.  The parameters you are passing to ReadStream() tell the
connection to simply keep reading the data into the stream until a
disconnect occurs.

Quote
> I am not sure how to tell the server a new file is coming.

Don't use WriteFile() at all.  Open up your own stream for each file and
then call WriteStream() directly instead.  That way, you can specify true
for the AWriteByteCount parameter.  And then on the server end, get rid of
the while() loop altogether and then when you call ReadStream(), specify
false instead of true for the AReadUntilDisconnect parameter.

In other words:

    --- client ---

    for i := 0 to frmMain.listbox1.items.count - 1 do
    begin
        try
            t1 := frmMain.listbox1.items[i];
            ftmpStream := TFileStream(workpath + '\' + t1, fmOpenRead);
            try
                IdTCPClient1.WriteLn('FILE');
                IdTCPClient1.WriteLn(t1);
                IdTCPClient1.WriteStream(ftmpStream, True, True, 0);
            finally
                FreeAndNil(ftmpStream);
            end;
        except
            on E: Exception do Showmessage(E.Message);
        end;
    end;

    --- server ---

    if sCommand = 'FILE' then
    begin
        t1 := AThread.Connection.Readln;
        ftmpStream := TFileStream.Create(workpath + '\' + t1, fmCreate);
        try
            AThread.Connection.ReadStream(fTmpStream, -1, False);
        finally
            FreeAndNil(fTmpStream);
        end;
    end;

Quote
> I am sending the "FILE" command ahead of every single file.

Yes, but you are only reading the "FILE" on the server end for the first
file and ignoring the rest.

Gambit

Re:Indy TCP Client / Server WriteFile Problem


You are an absolute legend. Thank you very, very much for your help!!

Regards,
Dominik.

Quote
Remy Lebeau (TeamB) wrote:
> "Dominik Moreitz" <dmore...@remove.hotmail.com> wrote in message
> news:3ee91a52$1@newsgroups.borland.com...

>>You are absolutely right. I sent 1 hlp and 2 txt files,
>>and the resulting hlp file was as big as all 3 put
>>together. I did not spot this because the help file
>>opens perfectly (which is even more bizarre).

> That is because the first part of the saved file contained correct HLP data,
> and everything is relative to the beginning of the file, so there was no
> reason for the Help system to complain, everything was located where it was
> supposed to be.  Had you transmitted a different file first, then it would
> have blown up on you instead.

>>if sCommand = 'FILE' then
>>begin
>>    t1 := AThread.Connection.Readln;
>>    ftmpStream := TFileStream.Create(workpath+'\'+t1,fmCreate);
>>    while AThread.Connection.Connected do
>>       AThread.Connection.ReadStream(fTmpStream,-1,true);
>>    FreeAndNil(fTmpStream);
>>end;

> Yup, you're reading all of the files into the same storage file on the
> receiving end.  The parameters you are passing to ReadStream() tell the
> connection to simply keep reading the data into the stream until a
> disconnect occurs.

>>I am not sure how to tell the server a new file is coming.

> Don't use WriteFile() at all.  Open up your own stream for each file and
> then call WriteStream() directly instead.  That way, you can specify true
> for the AWriteByteCount parameter.  And then on the server end, get rid of
> the while() loop altogether and then when you call ReadStream(), specify
> false instead of true for the AReadUntilDisconnect parameter.

> In other words:

>     --- client ---

>     for i := 0 to frmMain.listbox1.items.count - 1 do
>     begin
>         try
>             t1 := frmMain.listbox1.items[i];
>             ftmpStream := TFileStream(workpath + '\' + t1, fmOpenRead);
>             try
>                 IdTCPClient1.WriteLn('FILE');
>                 IdTCPClient1.WriteLn(t1);
>                 IdTCPClient1.WriteStream(ftmpStream, True, True, 0);
>             finally
>                 FreeAndNil(ftmpStream);
>             end;
>         except
>             on E: Exception do Showmessage(E.Message);
>         end;
>     end;

>     --- server ---

>     if sCommand = 'FILE' then
>     begin
>         t1 := AThread.Connection.Readln;
>         ftmpStream := TFileStream.Create(workpath + '\' + t1, fmCreate);
>         try
>             AThread.Connection.ReadStream(fTmpStream, -1, False);
>         finally
>             FreeAndNil(fTmpStream);
>         end;
>     end;

>>I am sending the "FILE" command ahead of every single file.

> Yes, but you are only reading the "FILE" on the server end for the first
> file and ignoring the rest.

> Gambit

Other Threads