🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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

TClientSocket handling a bad connection

#379
From: Lesley Anne
Date: Mon, 31 Mar 2008 22:34
123 lines
5982 bytes
(BCB6)
I have two apps, one using TClientSocket, one using TServerSocket, both in 
non-blocking mode.  Across a LAN, it works.  Across a WAN, it sometimes 
works, but we get the following failure about once each day:

1) Client tries to connect to the server.
Both Client and Server get OnConnect event.

2) Client calls SendText to send a message to the server.
Server sees nothing.
Client gets OnError event with: ErrorEvent == eeSend, ErrorCode == 10038 
(WSAENOTSOCK)
Within the OnError event handler, Client calls Socket->Close()
No OnDisconnect events occur, and Client remains Active.

3) Every second, the Client calls SendText a few more times.
Nothing reaches the server.

4) After 5 minutes, the server times out, deciding that this connection 
(which it hasn't received anything on) is bad, so closes it.
Server gets OnDisconnect event.
Client sees nothing.

5) Client (which is still Active and has never gotten an OnDisconnect event) 
continues trying to send on this connection which had never worked properly 
and which now no longer even exists at the server's end.


I think part of the fix is likely to be that I should redesign the client 
app to be multi-threaded so that I can use blocking sockets.  That way at 
least the client will be able to recognize that the SendText didn't work in 
time for me to avoid removing the message from the FIFO queue I use for 
spooling messages that need to be sent.  That's more of a symptomatic fix, 
though.  It doesn't really address the issue of why the error is occurring 
in the first place.

Both sides of the connection did see the OnConnect event.  Shouldn't that 
indicate that the connection was established successfully?  So why does the 
client get the WSAENOTSOCK error when it tries to send?  And why does it 
never get the OnDisconnect event?  If the connection is down, how can I 
force the client to recognize that it's down, so that I can stop sending and 
try to reconnect until I get a working connection?  (Calling Socket->Close 
from the OnError event was an attempt to do this.  I was hoping that would 
bring down the client side of the non-functioning "connection", so I could 
re-establish it.)



I'm not quite sure which is the most relevant part of the code, but sending 
is where the error occurs, so here's where I get to the SendText call from 
the client.  I could include other parts of the source, but they don't do 
much.  The OnConnect and OnDisconnect events just update status indicators 
on the screen and write to a logfile to let me know they happened.  The 
OnError event does the same, plus calls Socket->Close() as I already 
mentioned.

(BESpoolHead is a global pointer to the first node in a linked list.  It's a 
FIFO queue of messages that need to be sent.)

// -----------------------------------------------------------------------
void __fastcall TCnamForm::PerSecondTimer(TObject *Sender)
{
   TStringSpoolNode *TempNode;

   for (int i=0; BESpoolHead && (i<500); i++) {
      if (SendToBE(BESpoolHead->Data)) {
         TempNode = BESpoolHead->Link;
         delete BESpoolHead;
         BESpoolHead = TempNode;
      }
      else break;
   }
}
// -----------------------------------------------------------------------
bool TCnamForm::SendToBE(AnsiString Message)
{
   bool Success = false;

   if (BEClientSocket->Active) {
      try {
         BEClientSocket->Socket->SendText(Message + "\n");
         Success = true;
      }
      catch (Exception &E) {
         LogMessage("ERROR Sending to Back End. Exception: " + E.Message);
      }
   }

   return Success;
}
// -----------------------------------------------------------------------

One of my problems here is that, since I'm in non-blocking mode, that 
try-catch around SendText isn't really doing anything very useful.  That's 
why I think I need to redesign this to use blocking sockets, so I can see 
whether the send really was successful before deciding whether I can take 
the message off of the spool.

Oh, here's another part of the code that looks relevant.  I have a timer 
that runs continuously and re-establishes the connection if it's down and 
needs to be up.  (The BEIndicator->Brush->Color it references gets set to 
clLime during OnConnect and set to clRed in either the OnError or 
OnDisconnect event.  NeedBEConnect is a global bool which is true throughout 
the time that all this is happening.)

// -----------------------------------------------------------------------
void __fastcall TCnamForm::ReconnectTimerTimer(TObject *Sender)
{
   bool BackEndIsDown = ((!BEClientSocket->Active) || 
(BEIndicator->Brush->Color != clLime));

   if (NeedBEConnect && BackEndIsDown) {
      try {
         BEClientSocket->Close();
         BEClientSocket->Open();
      }
      catch (Exception &E) {
         LogMessage("ERROR Opening Back End Socket.  Exception: " + 
E.Message);
      }
   }
}
// -----------------------------------------------------------------------
Technical Details
Message-ID: <47f16766$1@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news3.google.com!proxad.net!feeder1-2.proxad.net!194.25.134.126.MISMATCH!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail

Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,74b475fd14f26423,start
X-Google-Attributes: gid11508e,domainid0,public,usenet
X-Google-Language: ENGLISH,ASCII-7-bit
From: "Lesley Anne" <mspfila (dash) brl (at) yahoo (dot) com>
Newsgroups: borland.public.cppbuilder.internet.socket
Subject: TClientSocket handling a bad connection
Date: Mon, 31 Mar 2008 18:34:12 -0400
Lines: 125
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2900.3138
X-RFC2646: Format=Flowed; Original
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3198
NNTP-Posting-Host: 144.160.5.25
Message-ID: <47f16766$1@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1207002982 144.160.5.25 (31 Mar 2008 15:36:22 -0700)
Path: arc1-ca.pugleaf.net!g2news1.google.com!news3.google.com!proxad.net!feeder1-2.proxad.net!194.25.134.126.MISMATCH!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail