Checking if a socket is connected

Testing if a socket is still open isn’t as easy at it sounds. Anyone who has ever dealt with socket programming knows this is hassle. The general pattern is to poll on the socket to see if its still available, usually by sitting in an infinite loop. However, with f# this can be done more elegantly using async and some decoupled functions.

First lets write an async function that monitors a socket and returns true if its connected or false if its not. The polling interval is set to 10 microseconds. This is because if you set the interval to a negative integer (representing to wait indefinitely for a response), it won’t return until data is written to the socket. If, however, you have a very short poll time, you will be able to detect when the socket is closed without having to write data to it.

/// Async worker to say whether a socket is connected or not
let isConnected (client:TcpClient) =         
    async { 
        return  
            try
                if client.Client.Poll(10, SelectMode.SelectWrite) && not <| client.Client.Poll(10, SelectMode.SelectError)  then
                    let checkConn = Array.create 1 (byte 0)
                    if client.Client.Receive(checkConn, SocketFlags.Peek) = 0 then
                        false
                    else 
                        true
                else
                    false
            with
                | exn -> false
    }

Next we can create a simple monitor function to check on a predicate, and if the predicate returns false (i.e not connected) it’ll execute an action. Otherwise it’ll call itself and monitor the socket again. This is important since the poll will exit once it determines that the socket is connected or not.

let rec monitor predicate onAction client  = 
    async {
        let! isConnected = predicate client
        if not isConnected then
            onAction client
        else 
            return! monitor predicate onAction client
    }

Then, to use the monitor function all you have to do is something like this

monitor isConnected onDisconnect client |> Async.Start

Where monitor is the generic async monitor function, isConnected is the async socket poll, onDisconnect is a function to call when a client disconnects, and client is a tcpClient socket connection. The great thing about this is that you don’t need to have a seperate thread for each open connection to act as a monitor/handler.

One comment

  1. Pingback: F# Weekly #4, 2014 | Sergey Tihon's Blog

Post a comment

You may use the following HTML:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>