🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.internet.socket
6 messages
6 total messages Started by Chris Tue, 02 Jan 2007 16:58
Using ReceiveBuff() from a client socket app?
#1570
Author: Chris
Date: Tue, 02 Jan 2007 16:58
256 lines
8673 bytes
Before the Holidays I had asked a question in the "ide" group 
about my method of sending jpegs through a socket connection. 
The response to my questions were good except for one problem I 
can't seem to fix. Just to refresh, below is the code that was 
sent to me on the server side and seems to work well.

***************************************************************
***************************************************************
#3 and #4 are good reasons NEVER to use SendStream() at all.  Use SendBuf()
instead, and pay attention to the return value.

Try this instead:

    void __fastcall SendBuf(TCustomWinSocket *Socket, void *Buffer, int
BufSize)
    {
        LPBYTE pBuf = (LPBYTE) Buffer;

        try
        {
            while( BufSize > 0 )
            {
                int NumSent = Socket->SendBuf(pBuf, BufSize);
                if( NumSent < 1 )
                {
                    if( (NumSent == -1) && (WSAGetLastError() ==
WSAEWOULDBLOCK) )
                    {
                        Application->ProcessMessages();
                        continue;
                    }
                    return false;
                }

                pBuf += NumSent;
                BufSize -= NumSent;
            }
        }
        catch(const Exception &)
        {
            return false;
        }
        return true;
    }

    bool __fastcall SendStream(TCustomWinSocket *Socket, TStream *Stream)
    {
        BYTE buffer[1024];
        int Size = Stream->Size;

        int NumToSend = (Size - Stream->Position);

        if( !SendBuf(Socket, &NumToSend, sizeof(NumToSend)) )
            return false;

        try
        {
            while( NumToSend > 0 )
            {
                int NumRead = Stream->Read(buffer, min(NumToSend,
sizeof(buffer)));
                if( NumRead < 1 )
                    return false;

                if( !SendBuf(Socket, buffer, NumRead) )
                    return false;

                NumToSend -= NumRead;
            }
        }
        catch(const Exception &)
        {
            return false;
        }

        return true;
    }


    while( !stop_images )
    {
        try
        {
            Application->ProcessMessages();
            if( stop_images )
                return;

            // set begin size of image as zero
            strm.Size(0);

            client.Image(strm, imFULL);// imHALF and imFULL

            strm.Position(0);
            strm.Save(strFileName.c_str());

            if( ServerSocket1->Socket->ActiveConnections > 0 )
            {
                TCustomWinSocket *socket =
ServerSocket1->Socket->Connections[0]; // use an appropriate index

                TStream* ftream = new TFileStream(strFileName.c_str(),
fmOpenRead | fmShareDenyWrite);
                try
                {
                    SendStream(socket, fstream);
                }
                __finally {
                    delete fstream;
                }
            }
        }
        catch(const Exception &)
        {
        }
    }

On the client side, you can read the first 4 bytes to get the stream size,
and then use ReceiveBuf() to keep reading until the specified number of
bytes have been recieved before then processing the stream data as needed.

***************************************************************
***************************************************************


The problem that I am having now is on the client side. I do 
recieve the the first 4 bytes using ReceiveBuff() to get the 
correct size that I am trying to receive. However, when I use 
ReceiveBuff() for the second time to start receiving the 1st 
packet, I get an error, "Asynchronous socket error 10053."

For the OnRead Event of the Client Socket I call a function 
called DrawImage(). Below is my code:

//------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Read(TObject *Sender,
      TCustomWinSocket *Socket)
{
         if(connected && !client_reading){
                CurrentBufferPosition++;

                if(LastBufferPosition == CurrentBufferPosition - 1){
                        client_reading = true;
                        DrawImage(Socket);
                        client_reading = false;
                }
         }
}
//---------------------------------------------------------------------------

bool TForm1::DrawImage(TCustomWinSocket *socket)
{
        TStream* fstream;

        try{
                if(CurrentBufferPosition == 1){
                        int buffSize = GetStreamSize(socket);
                        bufferSize = buffSize;
                }
                else if(bufferSize > 0){                    
                        ReceiveStream(socket,bufferSize, ftream);
                }
        }
        catch(const Exception &)
        {
            return false;
        }

        return true;
}
//------------------------------------------------------------------------------
bool __fastcall TForm1::ReceiveStream(TCustomWinSocket *socket, int Size,  TStream *Stream)
{
        void *buffer;

        try{
                
             
                while( Size > 0 )
                {
                        Application->ProcessMessages();
                    

                        int NumToReceive = socket->ReceiveLength();   
                        int NumReceived = socket->ReceiveBuf(buffer, NumToReceive);


                        if( NumReceived < 1 )
                        {
                                if( (NumReceived == -1) && (WSAGetLastError() == WSAEWOULDBLOCK) )
                                {
                                        
                                        Application->ProcessMessages();
                                        continue;
                                }
                                return false;
                        }

                        if(NumToReceive == NumReceived)
                        {
                                Stream->Write(buffer,Stream->Position);
                                //buffStream += buffer;
                                bufferSize -= NumReceived;
                                LastBufferPosition = CurrentBufferPosition;

                                if(bufferSize == 0){
                                        LastBufferPosition = 0;
                                        CurrentBufferPosition = 0;
                                }

                               

                        }
                        else
                                return false;
                    //}
                }
             
        }
        catch(const Exception &)
        {
            return false;
        }


        return true;
}
//------------------------------------------------------------------------------
int TForm1::GetStreamSize(TCustomWinSocket *socket)
{
        int Size = 0;
        void *buffSize = &Size;

        try{
                int NumToReceive = socket->ReceiveLength();                  int NumReceived = socket->ReceiveBuf(buffSize, NumToReceive); 
                
                if(NumToReceive == NumReceived){
                        LastBufferPosition = CurrentBufferPosition;
                        return Size;
                }
                else
                        return 0;
        }
        catch(const Exception &)
        {
            return 0;
        }
}
//------------------------------------------------------------------------------

I have tried using different ports as well. I appreciate any 
help on my problem.

Thanks,

Chris
Re: Using ReceiveBuff() from a client socket app?
#1572
Author: Remy Lebeau (TeamB)
Date: Tue, 02 Jan 2007 17:17
103 lines
3895 bytes
"Chris" <nospam@help.com> wrote in message
news:459a8f2a$1@newsgroups.borland.com...

> The problem that I am having now is on the client side. I do
> recieve the the first 4 bytes using ReceiveBuff() to get the
> correct size that I am trying to receive. However, when I use
> ReceiveBuff() for the second time to start receiving the 1st
> packet, I get an error, "Asynchronous socket error 10053."

Your reading code is completely wrong.  When using a non-blocking
socket, you can't read the entire stream inside a single event.  When
the OnRead event is triggered, you have to read whatever is actually
available, buffer it somewhere, and then wait for the event to be
triggered again later on to buffer more data.  You can then run
through the buffer whenever full packets are available for processing.

Try this instead:

    private:
        TMemoryStream *InboundBuffer;

    __fastcall TForm1::TForm1(TComponent *Owner)
        : TForm(Owner)
    {
        InboundBuffer = new TMemoryStream;
    }

    __fastcall TForm1::~TForm1()
    {
        delete InboundBuffer;
    }

    void __fastcall TForm1::ClientSocket1Connect(TObject *Sender,
TCustomWinSocket *Socket)
    {
        InboundBuffer->Clear();
    }

    void __fastcall TForm1::ClientSocket1Disconnect(TObject *Sender,
TCustomWinSocket *Socket)
    {
        InboundBuffer->Clear();
    }

    void __fastcall TForm1::ClientSocket1Read(TObject *Sender,
TCustomWinSocket *Socket)
    {
        int len = Socket->ReceiveLength();
        if( len < 1 )
            return;

        int old = InboundBuffer->Size;
        InboundBuffer->Size = (old + len);
        LPBYTE ptr = ((LPBYTE)InboundBuffer->Memory) + old;

        try
        {
            len = Socket->ReceiveBuf(ptr, len);
            if( len < 0 )
                len = 0;
        }
        catch(const Exception &)
        {
            len = 0;
        }

        InboundBuffer->Size = (old + len);
        if( len < 1 )
            return;

        InboundBuffer->Position = 0;
        while( (InboundBuffer->Size - InboundBuffer->Position) >=
sizeof(int) )
        {
            InboundBuffer->Read(&len, sizeof(int));
            if( (InboundBuffer->Size - InboundBuffer->Position) <
len )
            {
                InboundBuffer->Seek(-sizeof(int), soFromCurrent);
                break;
            }

            // read len bytes from InboundBuffer as use as needed ...
        }

        if( InboundBuffer->Position > 0 )
        {
            len = (InboundBuffer->Size - InboundBuffer->Position);
            if( len > 0 )
            {
                ptr = (((LPBYTE)InboundBuffer->Memory) +
InboundBuffer->Position);
                MoveMemory(InboundBuffer->Memory, ptr, len);
                InboundBuffer->Size = len;
            }
            else
                InboundBuffer->Clear();
        }
    }


Gambit
Re: Using ReceiveBuff() from a client socket app?
#1571
Author: Bob Gonder
Date: Tue, 02 Jan 2007 17:37
39 lines
2178 bytes
Chris wrote:

>On the client side, you can read the first 4 bytes to get the stream size,

You aren't doing that correctly.

>For the OnRead Event of the Client Socket I call a function 
>called DrawImage(). Below is my code:

The rest seems overly convoluted.

But this bit is also very wrong:

>bool __fastcall TForm1::ReceiveStream(TCustomWinSocket *socket, int Size,  TStream *Stream)
>{
>        void *buffer;
>     int NumReceived = socket->ReceiveBuf(buffer, NumToReceive);

Where is ReceiveBuf going to put the data?



>int TForm1::GetStreamSize(TCustomWinSocket *socket)
>{
>        int Size = 0;
>        void *buffSize = &Size;
>        try{
>                int NumToReceive = socket->ReceiveLength();

There might be more (or less) than 4 bytes available.
Only read 4 bytes, no more, no less.

>                int NumReceived = socket->ReceiveBuf(buffSize, NumToReceive); 

                int NumReceived = socket->ReceiveBuf( &Size, 4 );
 
Better would be to have a function (similar to the server send code)
that guarantees that Size bytes have been read from the socket.
               
Re: Using ReceiveBuff() from a client socket app?
#1573
Author: chris
Date: Tue, 02 Jan 2007 18:08
19 lines
1816 bytes

>Where is ReceiveBuf going to put the data?

My goal is to create a stream piece by piece and then display 
it as a TJPEG image. (Basically I want the images coming in to However, I haven't developed the code for 
that yet because I have not been able to receive the 
information that I want to receive. I have been temporarily 
using "void * buffer" just to bring the information in as I 
step through my code.

Also, I am trusting that the very first piece of info sent 
from the server is the first 4 bytes. That is why I never 
specified the the size of 4. I was trying to make my client 
code be close to a mirror image of the server code, and because of that I assume that the first amount of data is 4 bytes. I know my code was not fully completed, but I just wanted to be able to step through my program and see the information being pulled in correctly and error free before I moved on. 

Thanks again, 

Chris
Re: Using ReceiveBuff() from a client socket app?
#1574
Author: Remy Lebeau (TeamB)
Date: Tue, 02 Jan 2007 18:20
30 lines
2031 bytes
"chris" <nospam@help.com> wrote in message
news:459a9fb9$1@newsgroups.borland.com...

> I have been temporarily using "void * buffer" just to bring the
> information in as I step through my code.

The issue Bob was trying to point out to you is that you are reading
into a void* pointer that is not actually pointing anywhere.  You did
not allocate any memory for it.

> Also, I am trusting that the very first piece of info sent
> from the server is the first 4 bytes.

Don't trust anything.  That is a good way for a middleman attacker to
crash your code.  Or just connecting to the wrong server (user error)
could do it as well.  Always validate everything you send/receive.
You may want to prefix your packets with an actual header that
includes more information than just the packet size.  You could put
checksum information in it to verify the data before you try to use
it.

> I was trying to make my client code be close to a mirror image of
> the server code

It can't be a mirror when using non-blocking sockets.  The reading is
very different than the writing.


Gambit
Re: Using ReceiveBuff() from a client socket app?
#1575
Author: chris
Date: Tue, 02 Jan 2007 19:41
6 lines
1158 bytes
Thanks for all of your responses. I understand what I am trying to do much better now than I did before. That should be enough groundwork for me to get this thing working. Sorry for the messy/unorganized code that I posted earlier. 

Thanks again,

Chris
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads