🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.internet.socket
Article #4930

Re: how to send buffer size message and buffer

#4930
From: Remy Lebeau (TeamB)
Date: Wed, 17 Nov 2004 18:08
163 lines
5403 bytes
"hans galema" <notused@notused.nl> wrote in message
news:419b32cf$1@newsgroups.borland.com...

> You have to keep track on what is received yourself.
<snip>

Although that code snippet shows the basics, what it does not show you, and
that you need to take into account, is that when the OnRead event is
triggered, not all of the data may be available at one time.  OnRead may be
triggered multiple times before you receive the full buffer.  As such, you
need to maintain a separate buffer, and keep putting all of the received
bytes into the buffer until you have the full buffer available, and only
then process it.  For example:


    void __fastcall WriteRawToSocket(TCustomWinSocket *ASocket, void *AData,
int ASize)
    {
        BYTE *Ptr = (BYTE*) Data;
        int Sent;

        while( ASize > 0 )
        {
            Sent = ASocket->SendBuf(Ptr, ASize);
            if( Sent > -1 )
            {
                Ptr += Sent;
                ASize -= Sent;
            }
            else if( WSAGetLastError() != WSAEWOULDBLOCK )
                return;
        }
    }

    void __fastcall ReadRawFromSocket(TCustomWinSocket *ASocket, void
*AData, int ASize)
    {
        BYTE *Ptr = (BYTE*) Data;
        int Read;

        while( ASize > 0 )
        {
            Read = ASocket->ReceiveBuf(Ptr, ASize);
            if( Read > -1 )
            {
                Ptr += Read;
                ASize -= Read;
            }
            else if( WSAGetLastError() != WSAEWOULDBLOCK )
                return;
        }
    }

    void __fastcall WriteIntegerToSocket(TCustomWinSocket *ASocket, int
AValue)
    {
        WriteRawToSocket(ASocket, &AValue, sizeof(int));
    }

    int __fastcall ReadIntegerFromStream(TStream *AStream)
    {
        int Result = 0;
        AStream->Read(&Result, sizeof(int));
        return Result;
    }

    void __fastcall WriteStreamToSocket(TCustomWinSocket *ASocket, TStream
*AStream)
    {
        BYTE buffer[1024];
        int StreamSize = AStream->Size;
        WriteIntegerToSocket(ASocket, StreamSize - AStream->Position);
        while( AStream->Position < StreamSize )
        {
            int Bytes = (StreamSize - AStream->Position);
            if( Bytes > 1024 ) Bytes = 1024;
            int Read = AStream->Read(buffer, Bytes);
            WriteRawToSocket(ASocket, buffer, Read);
        }
    }


    class TMyMemoryStream : public TMemoryStream
    {
    public:
        TMyMemoryStream() : TMemoryStream() {}
        void* __fastcall Expand(int ABytes);
        int __fsatcall RemainingBytes();
        void __fastcall Remove(int ABytes);
    };

    void* __fastcall TMyMemoryStream::Expand(int ABytes)
    {
        int OldSize = Size;
        Size = (OldSize + ABytes);
        return (((BYTE*) Memory) + OldSize);
    }

    int __fastcall TMyMemoryStream::RemainingBytes()
    {
        return (Size - Position);
    }

    void __fastcall TMyMemoryStream::Remove(int ABytes)
    {
        int NewSize = (Size - ABytes);
        if( NewSize <= 0 )
        {
            Clear();
            return;
        }

        void* Ptr = (((BYTE*) Memory) + ABytes);
        System::Move(Ptr, Memory, NewSize);
        Size = NewSize;
        Position = 0;
    }


    private:
        TMyMemoryStream *FBuffer;

    __fastcall TServerForm::TServerForm(TComponent *AOwner)
        : TForm(AOwner)
    {
        FBuffer = new TMyMemoryStream;
    }

    __fastcall TServerForm::~TServerForm()
    {
        delete FBuffer;
    }

    void __fastcall TServerForm.ServerSocketClientRead(TObject *Sender,
TCustomWinSocket *Socket)
    {
        int BufLen = Socket->ReceiveLength();
        if( BufLen <= 0 ) return;

        void *Ptr = FBuffer->Expand(BufLen);
        ReadRawFromSocket(Socket, Ptr, BufLen);

        while( FBuffer->RemainingBytes() >= sizeof(int) )
        {
            BufLen = ReadIntegerFromStream(FBuffer);
            if( FBuffer->RemainingBytes() < BufLen )
            {
                FBuffer->Position = 0;
                break;
            }

            if( BufLen > 0 )
            {
                ReadRawFromStream(FBuffer, SomeBuffer, BufLen);
                // process SomeBuffer as needed...
                FBuffer->Remove(FBuffer->Position);
            }
        }
    }


Gambit
Technical Details
Message-ID: <419b934b$1@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news3.google.com!news.glorb.com!border1.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!nntp.giganews.com!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail
References: <419b3068$1@newsgroups.borland.com> <419b32cf$1@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,e51687cce2165a07
X-Google-Attributes: gid11508e,public
X-Google-Language: ENGLISH,ASCII-7-bit
From: "Remy Lebeau \(TeamB\)" <no.spam@no.spam.com>
Newsgroups: borland.public.cppbuilder.internet.socket
References: <419b3068$1@newsgroups.borland.com> <419b32cf$1@newsgroups.borland.com>
Subject: Re: how to send  buffer size message and buffer 
Date: Wed, 17 Nov 2004 10:08:56 -0800
Lines: 165
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1409
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1409
NNTP-Posting-Host: 68.69.17.41
Message-ID: <419b934b$1@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1100714827 68.69.17.41 (17 Nov 2004 10:07:07 -0700)
Path: arc1-ca.pugleaf.net!g2news1.google.com!news3.google.com!news.glorb.com!border1.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!nntp.giganews.com!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail