🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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

Re: Client: ctNonBlocking -> Server: stThreadBlocking

#5255
From: Remy Lebeau (TeamB)
Date: Mon, 27 Sep 2004 19:54
169 lines
6074 bytes
"Vladimir Stefanovic" <spam@not.needed> wrote in message
news:415856d5@newsgroups.borland.com...

> How can I send data with TClientSocket
> in ctNonBlocking to Server.

The same way you send it with ctBlocking.  The only thing you have to watch
out for is that ctNonBlocking may not always be able to accept new data
because it may block the socket.  In that case, you have to check the return
value of SendBuf().  If it returns -1, you have to wait for the socket's
OnWrite event to be triggered before you can write data to the socket again.

> I have the sending code which only works when the mode
> is ctBlocking. What can I do to modify the code to work
> in ctNonBlocking mode?

The easily way is to simply call Application->ProcessMessages() inside your
loop whenever SendBuf() returns -1 so that OnWrite can be processed.  This
would essentially make the code act like blocking code..  -1 is *NOT* an
error for a non-blocking socket unless the OnError event is triggered.
Otherwise, -1 simply means that the socket would have been blocked, but the
socket is otherwise still valid.  For example (untested):

    void __fastcall TcliForm::SendButtonClick(TObject *Sender)
    {
        if( (!ClientSocket->Active) || (!ClientSocket->Socket->Connected) )
            return;

        SendButtonClick->Enabled = false;

        int NumberOfBytes = OutboxDataBuffer->Size;

        bool bSent = SendData(&NumberOfBytes, sizeof(int));
        if( bSent )
            bSent = SendData(OutboxDataBuffer->Memory, NumberOfBytes);

        if( !bSent )
            ShowMessage( "Error!" );

        SendButtonClick->Enabled = true;
    }

    bool __fastcall TcliForm::SendData(void* Buffer, int BufSize)
    {
        LPBYTE pBuffer = (LPBYTE) pBuffer;
        int TotalSent = 0;

        try
        {
            while( TotalSent < BufSize )
            {
                int NumberOfBytesSent =
ClientSocket->Socket->SendBuf(&pBuffer[TotalSent], BufSize-TotalSent);
                if( NumberOfBytes == -1 )
                    Application->ProcessMessages();
                else
                    TotalSent += NumberOfBytes;
            }
            return true;
        }
        catch(const Exception &)
        {
            return false;
        }
    }


Otherwise, you will have to re-write the code to use a queing system
instead, for example (untested):

    #define APPWM_SEND_DATA    (WM_APP+100)

    __fastcall TcliForm::TcliForm(TComponent* Owner)
        : TForm(Owner)
    {
        OutboxDataBuffer = new TMemoryStream;
    }

    __fastcall TcliForm::~TcliForm()
    {
        delete OutboxDataBuffer;
    }

    void __fastcall TcliForm::SendButtonClick(TObject *Sender)
    {
        if( (!ClientSocket->Active) || (!ClientSocket->Socket->Connected) )
            return;

        TFileStream *FS = new TFileStream( ExtractFilePath( ParamStr(0) ) +
"test.txt" );
        try
        {
            int FileSize = FS->Size;
            OutboxDataBuffer->Write(&FileSize, sizeof(int));
            OutboxDataBuffer->CopyFrom(FS, FileSize);
        }
        __finally
        {
            delete FS;
            if( OutboxDataBuffer->Size > 0 )
                PostMessage(Handle, APPWM_SEND_DATA, 0, 0);
        }

        SendButton->Enabled = false;
    }

    void __fastcall TcliForm::ClientSocketWrite(TObject* Sender,
TCustomWinSocket* Socket)
    {
        if( OutboxDataBuffer->Size > 0 )
            PostMessage(Handle, APPWM_SEND_DATA, 0, 0);
    }

    void __fastcall TcliForm::WndProc(TMessage &Message)
    {
        if( Message.Msg == APPWM_SEND_DATA )
        {
            int Size = OutboxDataBuffer->Size;

            int NumberOfBytesSent = SendData(OutboxDataBuffer->Memory,
Size);
            if( NumberOfBytesSent > 0 )
            {
                if( NumberOfBytesSent == Size )
                    OutboxDataBuffer->Clear();
                else
                {
                    LPBYTE pSource = ( ((LPBYTE)OutboxDataBuffer->Memory) +
NumberOfBytesSent );
                    int NumberOfBytesLeft = (Size-NumberOfBytesSent);

                    ::MoveMemory(OutboxDataBuffer->Memory, pSource,
NumberOfBytesLeft);
                    OutboxDataBuffer->Size = NumberOfBytesLeft;
                }

                Size = OutboxDataBuffer->Size;
            }

            if( Size == 0 )
                SendButton->Enabled = true;
        }
        else
            TForm::WndProc(Message);
    }

    int __fastcall TcliForm::SendData(void* Buffer, int BufSize)
    {
        LPBYTE pBuffer = (LPBYTE) pBuffer;
        int TotalSent = 0;

        try
        {
            while( TotalSent < BufSize )
            {
                int NumberOfBytesSent =
ClientSocket->Socket->SendBuf(&pBuffer[TotalSent], BufSize-TotalSent);
                if( NumberOfBytes == -1 )
                    break;
                TotalSent += NumberOfBytes;
            }
        }
        catch(const Exception &) { }
        return TotalSent;
    }


Gambit
Technical Details
Message-ID: <41586fe3$1@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news.glorb.com!fr.ip.ndsoftware.net!newsfeed00.sul.t-online.de!t-online.de!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail
References: <415856d5@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,b3058d6528d1daa1
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: <415856d5@newsgroups.borland.com>
Subject: Re: Client: ctNonBlocking -> Server: stThreadBlocking
Date: Mon, 27 Sep 2004 12:54:15 -0700
Lines: 171
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: <41586fe3$1@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1096314851 68.69.17.41 (27 Sep 2004 12:54:11 -0700)
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news.glorb.com!fr.ip.ndsoftware.net!newsfeed00.sul.t-online.de!t-online.de!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail