🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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

Indy TCPServer, client disconnects not detected

#1520
From: Dennis Jones
Date: Sat, 13 Jan 2007 05:37
142 lines
6091 bytes
Hello,

I have a server application that uses the Indy TCPServer component.  I allow
any number of connections, but typically expect to see only one or two.  My
application has been working fine for about a year at numerous sites, but I
am now getting a report of my application basically hanging, or utilizing
too much CPU%, at a brand new site that is testing my app for use in their
environment.

In looking at my log files, I see incoming connections from a client
application, which sends a few messages and then...does nothing -- though
according to the customer, the client app disconnects.  However, my
application does not detect any form of client disconnect, graceful or
otherwise (no exceptions are thrown).  As far as my application is
concerned, the client is still connected.  Later, the client wants to send
some more messages, so it connects again, sends the messages, and
then...does nothing again.  Eventually, my app thinks there are 20, 30,
maybe 40 connections and the CPU utilization climbs way up to 80-90%.

Below is a *simplified* snippet of my TCPServerExecute method.  Note that
the majority of the code here is logging the various possible exception
cases.  Many of these exception cases are probably overkill, but they were
added in an effort to try to figure out when/where/if the client was
disconnecting (partiularly the generic ones), but none of the exception
cases are ever entered:

void __fastcall TMyServer::TCPServerExecute(TIdPeerThread *AThread)
{
   boost::scoped_ptr<TStringStream> AutoStream( new TStringStream("") );
   TStringStream *FStream = AutoStream.get();
   TMySpecialPeerThread *LThread = dynamic_cast<TMySpecialPeerThread
*>(AThread);
   try
   {
      static const int MsPerMin = 60000;

      // wait for data
      LThread->Connection->ReadFromStack( true,
                                          (FMaxIdleTime > 0)
                                             ? (FMaxIdleTime * MsPerMin)
                                             : IdTimeoutInfinite,
                                          true);
   }
   catch( EIdConnClosedGracefully &e )
   {
      // if EIdConnClosedGracefully occurs, the client has disconnected
      // normally; just exit
      LogMsg(AnsiString().sprintf( "Client disconnected gracefully. (%s)",
                                   e.Message.c_str() ));
      return;
   }
   catch( EIdReadTimeout &e )
   {
      try
      {
         // if EIdReadTimeout occurs, the client has been inactive for the
period
         // given by FMaxIdleTime (defined in minutes); forcibly disconnect
the
         // client and exit
         LogMsg(AnsiString().sprintf( "Disconnecting client due to
inactivity timeout. (%s)",
                                      e.Message.c_str() ));
         LThread->Connection->DisconnectSocket();
      }
      catch( const Exception &e )
      {
         LogMsg(AnsiString().sprintf( "An exception occured while
disconnecting client. (%s)",
                                      e.Message.c_str() ));
      }
      catch(...)
      {
         LogMsg("An unknown exception occured while disconnecting client.");
      }
      return;
   }
   catch( const Exception &e )
   {
      try
      {
         LogMsg(AnsiString().sprintf( "Disconnecting client due to a
connection exception. (%s)",
                                      e.Message.c_str() ));
         LThread->Connection->DisconnectSocket();
      }
      catch( const Exception &e )
      {
         LogMsg(AnsiString().sprintf( "An exception occured while
disconnecting client. (%s)",
                                      e.Message.c_str() ));
      }
      catch(...)
      {
         LogMsg("An unknown exception occured while disconnecting client.");
      }
      return;
   }
   catch(...)
   {
      try
      {
         LogMsg("Disconnecting client due to an unknown connection
exception.");
         LThread->Connection->DisconnectSocket();
      }
      catch( const Exception &e )
      {
         LogMsg(AnsiString().sprintf( "An exception occured while
disconnecting client. (%s)",
                                      e.Message.c_str() ));
      }
      catch(...)
      {
         LogMsg("An unknown exception occured while disconnecting client.");
      }
      return;
   }
   int FSize = (int)LThread->Connection->InputBuffer->Size;
   if ( FSize > 0 )
   {
      LogMsg(AnsiString().sprintf( "Received data (%d bytes) from client.",
FSize);

      FStream->Size = 0;
      LThread->Connection->ReadStream(FStream, FSize);
      LThread->Buffer = LThread->GetBuffer() + FStream->DataString;
   }
}

To my knowledge, this has never occured before, but maybe there is something
unusual about this particular client application.  Is there a "close packet"
(or something similar) that a TCP client uses to indicate to the server that
it is disconnecting?  Is it possible for a client to disconnect without the
server knowing it?

Any suggestions for how I might go about determining the cause of client
disconnects not getting detected?

Thanks in advance,

- Dennis
Technical Details
Message-ID: <45a86ffe$1@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news2.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail

Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,144f6b6a05bf12ad,start
X-Google-Attributes: gid11508e,public
X-Google-Language: ENGLISH,ASCII-7-bit
From: "Dennis Jones" <nospam@nospam.com>
Newsgroups: borland.public.cppbuilder.internet.socket
Subject: Indy TCPServer, client disconnects not detected
Date: Fri, 12 Jan 2007 21:37:16 -0800
Lines: 145
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2900.3028
X-RFC2646: Format=Flowed; Original
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3028
NNTP-Posting-Host: 71.245.109.58
Message-ID: <45a86ffe$1@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1168666622 71.245.109.58 (12 Jan 2007 21:37:02 -0800)
Path: arc1-ca.pugleaf.net!g2news2.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail