Tuesday, November 18, 2014

Socket Keep Alive IOControlCode Enumeration



IOControlCode Enumeration



Using IOControl code to configue socket KeepAliveValues for line disconnection detection (because default is toooo slow)

One option is to use TCP keep alive packets. You turn them on with a call to Socket.IOControl(). Only annoying bit is that it takes a byte array as input, so you have to convert your data to an array of bytes to pass in. Here's an example using a 10000ms keep alive with a 1000ms retry:


public void KeepConnectionAlive()
{
Socket tcpClient; //Make a good socket before calling the rest of the code.
tcpClient.Connect(ipAddress, port);
int size = sizeof(UInt32);
UInt32 on = 1;
UInt32 keepAliveInterval = 3000; //Send a packet once every 10 seconds.
UInt32 retryInterval = 1000; //If no response, resend every second.
byte[] inArray = new byte[size * 3];
Array.Copy(BitConverter.GetBytes(on), 0, inArray, 0, size);
Array.Copy(BitConverter.GetBytes(keepAliveInterval), 0, inArray, size, size);
Array.Copy(BitConverter.GetBytes(retryInterval), 0, inArray, size * 2, size);
tcpClient.IOControl(IOControlCode.KeepAliveValues, inArray, null);
}



/// TcpClient
/// The keep alive time. (ms)
/// The keep alive interval. (ms)


public static void SetTcpKeepAlive(Socket socket, uint keepaliveTime, uint keepaliveInterval)
        {
            /* the native structure
            struct tcp_keepalive {
            ULONG onoff;
            ULONG keepalivetime;
            ULONG keepaliveinterval;
            };
            */
             // marshal the equivalent of the native structure into a byte array
            uint dummy = 0;
            byte[] inOptionValues = new byte[System.Runtime.InteropServices.Marshal.SizeOf(dummy) * 3];
            BitConverter.GetBytes((uint)(keepaliveTime)).CopyTo(inOptionValues, 0);
            BitConverter.GetBytes((uint)keepaliveTime).CopyTo(inOptionValues, System.Runtime.InteropServices.Marshal.SizeOf(dummy));
            BitConverter.GetBytes((uint)keepaliveInterval).CopyTo(inOptionValues, System.Runtime.InteropServices.Marshal.SizeOf(dummy) * 2);

            // write SIO_VALS to Socket IOControl
            socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
        }
 
http://msdn.microsoft.com/en-us/library/system.net.sockets.iocontrolcode%28v=vs.110%29.aspx

No comments:

Post a Comment