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.