Account Options

  1. Sign in
Google Groups Home
« Groups Home
Message from discussion TServerSocket SendText Exception
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Remy Lebeau (TeamB)  
View profile  
 More options Apr 24 2006, 2:08 pm
Newsgroups: borland.public.cppbuilder.internet.socket
From: "Remy Lebeau \(TeamB\)" <no.s...@no.spam.com>
Date: Mon, 24 Apr 2006 11:08:43 -0700
Local: Mon, Apr 24 2006 2:08 pm
Subject: Re: TServerSocket SendText Exception

"Eric Patterson" <eric.patter...@bepco.com> wrote in message

news:444cd08c$1@newsgroups.borland.com...

> Do you think that the Invalid Pointer Exception is coming from
> the client not being present?

That is a possibility, if you are allowing messages to be processed while
you are still looping through the connections.  When a client disconnects,
the OnClientDisconnect event is triggered, and then the server posts a
CM_DEFERFREE message back to itself.  When that message is processed, the
client socket is freed immediately.  If you continue to access the socket
after it has been freed, then your code has undefined behavior from that
point on, and anything can happen.

> The system I have setup should always have a client present; I
> typically (and my test rig is setup this way) only have two client's
> connected to the server application.  They both get the same messages
> no matter what and they should never leave (or disconnect from the
> server).

You should not be relying on that behavior.  You are not allowing your code
to handle unforseen issues, such as network/power outages, transmission
errors, etc.

> Also you stated earlier that I can't keep doing a sendtext until I get
> a ClientWrite Event after a -1 was returned from a SendText.

Please re-read what I said.  What I actually said was that you have to call
WSAGetLastError() in order to find out why SendText() is returning -1.  The
OnWrite event be triggered later on only when WSAGetLastError() returns
WSAEWOULDBLOCK.  Any other value is an actual socket error and the socket
can no longer be used and must be reconnected.

> Now you are saying I have to do a SendText (pump the message queue)
> so I know the state of the socket.

Only for the specific code snippet that you showed, which would not work
given the way you showed it.  You are now relying on a variable that cannot
be set without the OnWrite event being triggered, and it cannot be triggered
while you are still running a loop until the loop pumps the message queue fo
r pending messages.

I strongly suggest that you go to http://www.deja.com and search through the
newsgroup archives.  I have posted sample code dealing with non-blocking
sockets and the OnWrite event on several different occasions.  For example,
here is a more reliable way to deal with queuing outbound data:

    void __fastcall TServer::ServerSocketClientConnect(TObject* Sender,
TCustomWinSocket* Socket)
    {
        Socket->Data = new TMemoryStream;
    }

    void __fastcall TServer::ServerSocketClientDisconnect(TObject* Sender,
TCustomWinSocket* Socket)
    {
        delete static_cast<TMemoryStream*>(Socket->Data);
        Socket->Data = NULL;
    }

    void __fastcall TServer::ServerSocketClientWrite(TObject* Sender,
TCustomWinSocket* Socket)
    {
        TMemoryStream *MS = static_cast<TMemoryStream*>(Socket->Data);
        if( MS->Size > 0 )
        {
            MS->Position = 0

            LPBYTE ptr = static_cast<LPBYTE>(MS->Memory);
            int sent;

            while( MS->Position < MS->Size )
            {
                sent = Socket->SendBuf(&ptr[MS->Position], MS->Size -
MS->Position);
                if( sent > 0 )
                    MS->Seek(sent, soFromCurrent);
                else
                    break;
            }

            if( MS->Position > 0 )
            {
                int remaining = (MS->Size - MS->Position);
                if( remaining > 0 )
                {
                    if( MS->Position > 0 )
                    {
                        Move(&ptr[MS->Position], MS->Memory, remaining);
                        MS->Size = remaining;
                    }
                }
                else
                    MS->Clear();
            }
        }
    }

    void __fastcall TServer::SendBufferToSocket(TCustomWinSocket *Socket,
void *Buffer, int BufSize)
    {
        TMemoryStream *MS = static_cast<TMemoryStream*>(Socket->Data);
        LPBYTE ptr = static_cast<LPBYTE>(Buffer);

        if( MS->Size == 0 )
        {
            int sent;

            while( BufSize > 0 )
            {
                sent = Socket->SendBuf(ptr, BufSize);
                if( sent > 0 )
                {
                    ptr += sent;
                    BufSize -= sent;
                    continue;
                }

                if( (sent == 0) || (WSAGetLastError() != WSAEWOULDBLOCK) )
                    return;

                break;
            }

            if( BufSize < 1 )
                return;
        }

        MS->Seek(0, soFromEnd);
        MS->WriteBuffer(ptr, BufSize);
    }

    void __fastcall TServer::SendTextToSocket(TCustomWinSocket *Socket,
const AnsiString &S)
    {
        SendBufferToSocket(Socket, S.c_str(), S.Length());
    }

    void __fastcall TServer::SendMsg(const AnsiString &AMsg)
    {
        for(int ii = 0; ii < ServerSocket1->Socket->ActiveConnections; ++ii)
            SendTextToSocket(ServerSocket1->Socket->Connections[ii], AMsg +
"\n");
    }

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        Server->SendMsg("whatever");
    }

Gambit


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.