🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.internet.socket
2 messages
2 total messages Started by JohnG Wed, 27 Feb 2008 13:52
Keep Alive & reconnecting
#475
Author: JohnG
Date: Wed, 27 Feb 2008 13:52
64 lines
2472 bytes
Hi,

I am using C++ Builder 2006 with indy 9 (9.0.50?) components.

I believe the "Keep Alive" code I have implemented in negatively
affecting the TIdTCPClients ability to reconnect to the
TidTCPServer. When a client reconnects prior to the server 
realizing that the connection was severed, the client 
disconnects immediately after reconnecting.

I believe (guess) that the Keep Alive code is in the process of
 failing as the client is reconnecting. If I remove the Keep 
Alive code, reconnections always succeeds. If I wait until the 
server realizes that the connections have severed, reconnections
always succeed.



I have the following code in a TimerEvent ( every 10 seconds) 
as my implementation of "Keep Alive" code between clients 
(TidTCPClient) and server

//code to ping\keep alive to all connected clients

TList *list = IdTCPServer->Threads->LockList();

try
{
  for( int i = 0 ; i < list->Count ; i++)
  {
    TIdPeerThread *thread = static_cast<TIdPeerThread*>(list->Items[i]);
   
    if (thread->Connection->Socket->Connected())
    {
       strResponse = SendMessageToClient(thread,strPING,8000 /* timeout value*/);
    }
    else
    {
		
       //return faillure
    }
  }

}
catch(...)
{
   IdTCPServer->Threads->UnlockList();
}

   
IdTCPServer->Threads->UnlockList();

//----------------------------------------------
The rest of my implementation is similar to this 

http://tinyurl.com/2bq4vt

Any ideas or suggestions on how to prevent the keep alive code
from affecting cient reconnections will be greatly appreciated.

Regards,

JohnG
Re: Keep Alive & reconnecting
#476
Author: Remy Lebeau (TeamB)
Date: Wed, 27 Feb 2008 18:27
93 lines
3940 bytes
"JohnG" <whatis@email.com> wrote in message 
news:47c57942$1@newsgroups.borland.com...

> I believe the "Keep Alive" code I have implemented in
> negatively affecting the TIdTCPClients ability to reconnect
> to the TidTCPServer. When a client reconnects prior to
> the server realizing that the connection was severed, the
> client disconnects immediately after reconnecting.

You should not be calling Connected() in your loop at all.  Just send the 
ping and catch any error that may occur.

> I believe (guess) that the Keep Alive code is in the process
> of failing as the client is reconnecting.

That would not have any effect on it.  Your loop knows which threads to send 
to.  If a client reconnects, it is going to have a completely new thread. 
Sending a ping to a previous thread will not effect the new thread at all.

> I have the following code in a TimerEvent ( every 10 seconds)
> as my implementation of "Keep Alive" code between clients
> (TidTCPClient) and server

I would not suggest using such a timed loop at all.  Let the OnExecute event 
handler perform the actual keepalive on a per-client basis for you.  You 
shouldn't be sending a ping unless a connection has actually been idle for 
awhile.  For example (untested):

    class TMyPeerThread : public TIdPeerThread
    {
    public:
        TDateTime LastRecv;
        __fastcall TMyPeerThread(bool ACreateSuspended = true);
    };

    __fastcall TMyPeerThread::TMyPeerThread(bool ACreateSuspended)
        : TIdPeerThread(ACreateSuspended)
    {
    }


    __fastcall TForm1::TForm1(TComponent *Owner)
        : TForm(Owner)
    {
        IdTCPServer1->ThreadClass = __classid(TMyPeerThread);
    }

    void __fastcall TForm1::IdTCPServer1Connect(TIdPeerThread *AThread)
    {
        AThread->Connection->ReadTimeout = 10000;
        static_cast<TMyPeerThread*>(AThread)->LastRecv = Now();
    }

    void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
    {
        TMyPeerThread *LThread = static_cast<TMyPeerThread*>(AThread);
        TDateTime dtNow = Now();

        if( LThread->Connection->InputBuffer->Size == 0 )
        {
            if( LThread->Connection->ReadFromStack(true, IdTimeoutDefault, 
false) < 0 )
            {
                if( SecondsBetween(dtNow, LThread->LastRecv) < 30 )
                {
                    // write PING command as needed. do not wait for a 
reply...
                }
                else
                    AThread->Connection->Disconnect();

                return;
            }
        }

        LThread->LastRecv = dtNow;

        // handle inbound data as needed...
    }

> catch(...)
> {
>    IdTCPServer->Threads->UnlockList();
> }
>
> IdTCPServer->Threads->UnlockList();

If an exception occurs in your loop, you are calling UnlockList() twice. 
Don't do that.


Gambit 
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