Automatic Reconnect Client Sockets

Scott Nichols I've been working on a Tcl network client for a while and have always wanted the client to be able to automatically reconnect to the server if the connection was lost. After much trial and error I finally was able to get it working the way I wanted and decided to share the code. The sample code below will try to reconnect to the server every 10 seconds when there is a problem. I am very happy with it. The auto-reconnect saves the end user some frustration and troubleshooting, and also protects from network hickups. This sample code also shows how to configure a client socket for nonblocking operation and also configure tdom's expat parser for situations when the large XML document may have been truncated during the initial read and the remainder sent during the next socket read. Comments are welcome.

 package require tdom
 set ::host someserver
 set ::port someport
 
 # Event Driven. Called everytime XML data comes in over the socket.
 proc SockListener {dataRead} {
    if { [eof $::sock] || [catch {$::parser parse [read $dataRead]}]} {
        puts "Socket read error, trying to reconnect in 10s"
        close $::sock
        after 10000 {EventPubConnect}
    }
 }

 # Called each time a new element arrives.
 proc HandleStart {name attlist} {

    catch {
        # Clear the global array
        array unset ::$name
    }
    catch {
        # Populate the array from the list
        array set ::$name $attlist
    }
 }
 
 # Called when XML end tag arrives.
 # NOTE: This is where you want to do the work.
 proc HandleEnd {name} {
   switch -exact -- $name { 
      SomeTag {
        # Do work
      }
      # Insert XML Tags
   }
 }

 # Connect to the XML server
 proc EventPubConnect { } {

    if { [catch {
    
        # Connect to the eventpub socket
        set ::sock [socket $::host $::port]

        # Configure the socket
        set fcon [fconfigure $::sock -buffering full -buffersize 64000 -blocking false]

        # Setup the receiving socket proc
        fileevent $::sock r [list SockListener $::sock]

        set ::parser [expat] 

        $::parser configure -final 0 -elementstartcommand HandleStart -elementendcommand HandleEnd

        puts "Connected to EventPub socket $::host:$::port"

    } errorString] } {
        log "proc EventPubConnect ERROR: \"$errorString\""
        after 10000 {EventPubConnect}
    }

 }
 EventPubConnect