Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Jun : Re: IdTCPClient.Socket.Recv - Hangs

www.cryer.info
Managed Newsgroup Archive

Re: IdTCPClient.Socket.Recv - Hangs

Subject:Re: IdTCPClient.Socket.Recv - Hangs
Posted by:"Remy Lebeau (TeamB)" (no.spam@no.spam.com)
Date:Wed, 21 Jun 2006 10:12:28

"brandon" <someone@microsoft.com> wrote in message
news:44996c39@newsgroups.borland.com...

> I am attempting to transfer a file with TidTCPClient and Server.
>
> I do not want to disconnect the client to indicate the file transfer
> is complete, so I have the following code wich works...Mostly.

You are doing it the wrong way.  You should not be accessing the lower-level
Socket methods directly at all.  Use the higher-level Connection methods
instead, such as WriteStream() and ReadStream().  For example:

    --- sending ---

    begin
        str := TFileStream.Create('c:\temp\tosend.jpg', fmOpenRead or
fmShareDenyWrite);
        try
            AThread.Connection.WriteStream(str, True, True);
        finally
            FreeAndNil(str);
        end;
    end;


    --- receiving ---

    begin
        str := TFileStream.Create('c:\temp\rcvd.jpg', fmCreate);
        try
            IdTCPClient1.ReadStream(str);
        finally
            FreeAndNil(str);
        end;
    end;

> The problem apears to be that when the last "chunk" of data is
> read, if it is less than the SizeOfBuffer, the application hangs.

That is because your code has no way of knowing when the end of file is
actually received, so it tries to read an entire buffer that will never
arrive.  Remember that Indy is a blocking library.  When you tell it to read
a particular size of data, it waits for all of the requested data to arrive
before continuing.  It is not like Borland's non-blocking sockets where you
can request a large buffer and it returns how much data was actually
received if smaller.  To do that, you would have to use the Connection's
ReadFromStack() method instead, and check how the Size of the InputBuffer
changes each time.

Just use Read/WriteStream() instead, it does all of that for you.  In the
code I show above, the parameters of WriteStream() are telling it to send
the stream's byte size before the actual data.  The default parameters of
ReadStream() tell it to expect that byte count to arrive so that it can know
when to stop reading.

> While the application is hung, the rcvd.jpg file size is 0.

That is because the file stream is still open.  The data has not been
flushed to the hard drive yet.

> Is there a timeout that needs to be set, or do I need to lay a
> trap for EOF,...?

You need to completely re-write your transferring code, since you are taking
the wrong approach to begin with.


Gambit

Replies:

In response to:

www.cryer.info
Managed Newsgroup Archive