Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Aug : Re: Problem reading data from TidIOHandler

www.cryer.info
Managed Newsgroup Archive

Re: Problem reading data from TidIOHandler

Subject:Re: Problem reading data from TidIOHandler
Posted by:"Remy Lebeau (TeamB)" (no.spam@no.spam.com)
Date:Tue, 15 Aug 2006 13:16:02

"Kiwi" <glen@custommadesoftware.co.nz> wrote in message
news:44e14282@newsgroups.borland.com...

> I am still having problems handling the data from the IOHandler

That is because you are still not handling it correctly.

> Here is the Server side code which seems to be working fine

Wrong.  It is not working correctly, because of the following ...

>     Buf:= RawToBytes(fMem, fMem.Size);

That line is wrong.  As I explained to you earlier, in order to access the
TMemoryStream's content, you must use its Memory property, ie:

    Buf := RawToBytes(fMem.Memory, fMem.Size);

You are not doing that, so you are trying to convert the raw data that is
located at the memory address where the TMemoryStream object itself is
stored, not where its data buffer is stored.  The two are NOT at the same
memory address!

>     Move(Buf[0], Buf[4], Length(Buf));

That is also wrong.  You are writing data past the end of the buffer, so you
are going to corrupt the surrounding memory, if not cause an AV instead.
Since you are using the new length instead of the original length, you need
to subtract 4 when copying the bytes:

    Move(Buf[0], Buf[4], Length(Buf)-4);

>         BytesToRaw(Buf, fMem, Size);
>         fMem.Position:= 0; <=====Failing here with an access violation

That is because you are still overwriting the value stored in the
TMemoryStream pointer incorrectly, as I explained to you earlier.  You MUST
set the TMemoryStream's Size property and then copy the bytes into the
TMemoryStream's Memory property instead, ie:

    fMem.Size := Size;
    BytesToRaw(Buf, fMem.Memory, Size);

With that said, you shouldn't be trying to stuff the TIdBytes length into
the TIdBytes itself to begin with.  Use the Write(Integer) and ReadInteger()
methods instead, ie:

    --- server ---

    Buf := RawToBytes(fMem.Memory, fMem.Size);
    AContent.Connection.IOHandler.Write(Integer(Length(Buf)));
    AContext.Connection.IOHandler.Write(Buf);


    --- client ---

    fMem := TMemoryStream.Create;
    try
        SetLength(Buf, 0);
        Size := IOHandler.ReadInteger;
        if Size > 0 then IOHandler.ReadBytes(Buf, Size, False);
        fMem.Size := Size;
        BytesToRaw(Buf, fMem.Memory, Size);
        fMem.Position := 0;
        fMem.Read(cmd, 4);
    finally
        fMem.Free;
    end;


Alternatively:

    --- server ---

    fMem.Position := 0;
    ReadTIdBytesFromStream(fMem, Buf, fMem.Size);
    AContent.Connection.IOHandler.Write(Integer(Length(Buf)));
    AContext.Connection.IOHandler.Write(Buf);


    --- client ---

    fMem := TMemoryStream.Create;
    try
        SetLength(Buf, 0);
        Size := IOHandler.ReadInteger;
        if Size > 0 then IOHandler.ReadBytes(Buf, Size, False);
        WriteTIdBytesToStream(fMem, Buf, Size);
        fMem.Position := 0;
        fMem.Read(cmd, 4);
    finally
        fMem.Free;
    end;


Even better, as I suggested to you earlier, you should get rid of the
TIdBytes altogether and read/write the streams directly.  Write(Stream) and
ReadStream() even handle the 4-byte length for you automatically.

    --- server ---

    AContext.Connection.IOHandler.Write(fMem, 0, True);


    --- client ---

    fMem := TMemoryStream.Create;
    try
        IOHandler.ReadStream(fMem, -1, False);
        fMem.Position := 0;
        fMem.Read(cmd, 4);
    finally
        fMem.Free;
    end;


Gambit

Replies:

none

In response to:

www.cryer.info
Managed Newsgroup Archive