Best way to detect why a tcp disconnection occurred

Hello all,

When using TCP, what is the best way to know the reason for a disconnect to occur? This is my first time working with TCP and am trying to code a reconnect when appropriate, and also prevent disconnects from occurring when not desired.

Any ideas would be appreciated.

Thanks,
Tim

There’s no real way to determine why a disconnect occurred, but you can trap the disconnect error in the error event of the socket - error code 102 & then initiate a reconnect or put the socket back into listening mode.

Tim,

I subclass TCPSocket and then add the following code to my .error event. You could wrap logic around receiving each event type etc.

// Error Check Control
If me.LastErrorCode <> 0 then

if me.LastErrorCode = 22 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + " You are attempting to write to a socket that has been disconnected.")
  
elseif me.LastErrorCode = 64 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + " You are attempting to connect to a host that is not responding.")
  
elseif me.LastErrorCode = 95 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + " Socket operation was attempted on a non-socket port.")
  
elseif me.LastErrorCode = 96 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + " Destination address is required.")
  
elseif me.LastErrorCode = 97 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + " Message was too long.")
  
elseif me.LastErrorCode = 98 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + " Protocol is the wrong type for this socket.")
  
elseif me.LastErrorCode = 99 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + " Protocol not available.")
  
elseif me.LastErrorCode = 100 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + " There was an error opening and initializing the drivers.")
  
elseif me.LastErrorCode = 102 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + " TCP/IP Socket Connection was terminated")
  
elseif me.LastErrorCode = 103 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + "  Unable to resolve hostname.")
  
elseif me.LastErrorCode = 105 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + "  The IP Address currently is in use.")
  
elseif me.LastErrorCode = 106 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + "  The Socket is in an invalid state.")
  
elseif me.LastErrorCode = 107 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + "  The Port number specified is invalid: [" + str(me.Port) + "]")
  
elseif me.LastErrorCode = 120 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + "  Protocol is not supported.")
  
elseif me.LastErrorCode = 125 then
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]" + "  The IP Address currently is in use.")
  
else 
  mLogFacility(1,"Error Code[" + str(me.LastErrorCode)+"]")
  Exit
End If

end if

HTH.

Thanks guys!

Within the app that does the disconnecting, is there any way to know why the connection was terminated? For example, some code somewhere (yes I know it is my job to monitor and control this one!) initiated the disconnect? Or there was a problem with the internet? Or a cable was cut or otherwise unplugged?

These may not be possible, but thought it worth asking the question!

Thank you both again.
Tim

Knowing that TCP is a layer 4 protocol it really has no idea what the physical layer and or layer 2 framing is doing. Each error code generally has a specific “reason” behind why it fires. Here is a good link also on TCPSockets for Real Studio which was a great resource for me also.

TCPSockets Readme (LJensen)

Also maybe reading RFC 793 for TCP may help you understand why a TCP socket acts a certain way when a RST/FIN bit is received to begin a session TCP teardown.

HTHRFC 793

[quote=30082:@Mike Cotrone]Tim,

I subclass TCPSocket and then add the following code to my .error event. You could wrap logic around receiving each event type etc.[/quote]

Out of curiosity, what OS are you using and how were these magic numbers derived?

Mac OS, Linux and I used the Linux Error codes and Mac OS specific error codes (ie. 22 for mac os).

Linux TCP Error Codes

Derived from /usr/include/asm/errno.h

[quote=30083:@Tim Seyfarth]Thanks guys!

Within the app that does the disconnecting, is there any way to know why the connection was terminated? For example, some code somewhere (yes I know it is my job to monitor and control this one!) initiated the disconnect? Or there was a problem with the internet? Or a cable was cut or otherwise unplugged?
[/quote]

Tim which target OS are you compiling for also? You may be able to monitor the OS’s ethernet status to check for physical issues.

Thanks again everyone!
Frankly I am a bit surprised by the level of activity on this subject. It kind of is a basic question - or so I thought. I know the generic codes, like 102, but am having trouble detecting why connections get dropped, and from which side, and of course WHY!? The who and why are the big things. Could be screwed up logic, bad code or any of other issues - I guess…

I will have a look at the links too. Having these object be so high in level, like the serial object, can sometimes make it much harder to understand and control. Conversely, the high level objects abstract so much complexity away, and have been written by people far smarter than I, so programming their use becomes almost simple!

Again everyone - Thank you!
Tim

Sorry Tim :slight_smile: I am a Cisco Network Engineer / Programmer so I have been working a lot on TCP Sockets lately. :slight_smile:

To really understand why a side disconnects (discounting what we spoke about above) you would need to look at a sniffer to see why Layer 7 had sent a TCP FIN which causes the other side to RST which tears down the TCP connection. As Wayne suggested using the Error codes with logic wrapped into it will be your ability to programmatically respond to any Three way TCP handshake disconnect.

  • Layer 7 had instructed TCP to send a TCP FIN ** (its late sorry)

Thanks Mike,

I will do so- that will help I think. Again, thank you!
TIm

Tim I also just realized that I didn’t post my mlogfacility logging Sub method from my above Error Code. (It is basic logging code)

Sub mLogFacility(logfacility as integer, message as String)
  Dim LogFile As FolderItem
  Dim Tos as TextOutputStream
  Dim TimeStamp as New Date
  Dim LogMessage as String
  
  // Implement log facility level
  
  LogFile = SpecialFolder.UserHome
  LogMessage = str(TimeStamp)+"   " + message +Chr(10)+Chr(13)
  
  for i as integer = UserLogFacility downto 1
    if LogFile <> nil AND LogFile.Exists AND LogFile.Directory then
      LogFile = SpecialFolder.UserHome.Child(kLogFileDir)
      if LogFile <> nil then
        if not LogFile.Exists then LogFile.CreateAsFolder
        if LogFile.Directory then
          LogFile = LogFile.Child(kLogFile)
          if LogFile <> nil then
            if not LogFile.Directory then
              if LogFile.Exists then
                Tos = TextOutputStream.append(LogFile)
                Tos.Write(LogMessage)
                Tos.Close
              else
                Tos = TextOutputStream.Create(LogFile)
                Tos.Write(LogMessage)
                Tos.Close
              end if
            end if
          end if
        end if
      end if
    end if
  next
  
End Sub

It’s worth noting that the POSIX specification does not make any guarantee as to the actual values that symbolic names (and actually goes out of its way to point this out). For example, EADDRINUSE defines to 48 on OS X, 98 on 32-bit x86 Linux, and 10048 on Windows. However, you probably could write a declare to strerror to get a reasonable message in a cross platform manner.

However… the Xojo framework provides no guarantee that SocketCore.LastErrorCode will be actually be a POSIX error number in the first place.

Thanks Joe! That is a great point and idea, but my programming skills stop quickly at declares :slight_smile: I tried to cross reference the MAC OS errors and errno.h errors that my TCP.Errors actually saw so that I could create meaningful text for my errors in my code example. Thank you for clarifying for cross platform since I don’t develop on Windows.

Thanks!