We are looking for a way to enable TCP keepalive for client sockets on Windows CE 6.0, using .net Compact framework 3.5.
So far I've found these options:
Set keepalive using SetSocketOption on the System.Net.Socket class:
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
This actually work, but uses the windows-global settings for keepalive, and that is to check the connection every second hour, which is way too seldom for our use case. This timeout setting can be changed (globally) by altering registry keys under [HKEY_LOCAL_MACHINE\Comm\Tcpip\Parms]. This will be my fallback solution, but I'd rather set the timeouts on a per-connection basis.
Then I have tried using socket.IoControl as suggested by several sources online to set this socket option including the timeout values, but it only results in an SocketException (“An invalid argument was supplied”).
Example
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// The native structure for this is defined in mstcpip.h as:
//struct tcp_keepalive {
//u_long onoff;
//u_long keepalivetime;
//u_long keepaliveinterval;
//};
//Set to on, 10 seconds and 1 second. From examples online u_long should be interpreted as unsigned 32bit.
byte[] inValue = new[] { (uint)1, (uint)10000, (uint)1000 }
.SelectMany(x => BitConverter.GetBytes(x))
.ToArray();
//0x98000004 is constant for SIO_KEEPALIVE_VALS found in mstcpip.h
int ioControlCodeKeepAliveValues = BitConverter.ToInt32(BitConverter.GetBytes(0x98000004), 0);
// Throws "An invalid argument was supplied" SocketException
socket.IOControl(ioControlCodeKeepAliveValues, inValue, null);
socket.Connect(new IPEndPoint(IPAddress.Parse("192.168.0.120"),80));
Is this code correct, or is it a known limitation of Windows CE 6 that keep-alive can not be set per connection?