Commentary adapted from these sites:
Introduction
In order to understand what TCP keepalive (which we will just call keepalive) does, you need do nothing more than read the name: keep TCP alive. This means that you will be able to check your connected socket (also known as TCP sockets), and determine whether the connection is still up and running or if it has broken.
Background
Understanding TCP keepalive is not necessary in most cases, but it's a subject that can be very useful under particular circumstances. You will need to know basic TCP/IP networking concepts.
What is TCP keepalive?
The keepalive concept is very simple: when you set up a TCP connection, you associate a set of timers. Some of these timers deal with the keepalive procedure. When the keepalive timer reaches zero, you send your peer a keepalive probe packet with no data in it and the ACK flag turned on. You can do this because of the TCP/IP specifications, as a sort of duplicate ACK, and the remote endpoint will have no arguments, as TCP is a stream-oriented protocol. On the other hand, you will receive a reply from the remote host (which doesn't need to support keepalive at all, just TCP/IP), with no data and the ACK set.
If you receive a reply to your keepalive probe, you can assert that the connection is still up and running without worrying about the user-level implementation. In fact, TCP permits you to handle a stream, not packets, and so a zero-length data packet is not dangerous for the user program.
This procedure is useful because if the other peers lose their connection (for example by rebooting) you will notice that the connection is broken, even if you don't have traffic on it. If the keepalive probes are not replied to by your peer, you can assert that the connection cannot be considered valid and then take the correct action.
Using the Code
The SetKeepAliveValues
method enables or disables the per-connection setting of the TCP keep-alive option which specifies the TCP keep-alive timeout and interval used for TCP keep-alive packets. For more information on the keep-alive option, see section 4.2.3.6 on the Requirements for Internet HostsCommunication Layers specified in RFC 1122 available at the IETF website.
The optionInValue
parameter that pass to Socket.IOControl
should point to a tcp_keepalive
structure defined in the Mstcpip.h header file. This structure is defined as follows:
struct tcp_keepalive {
u_long onoff;
u_long keepalivetime;
u_long keepaliveinterval;
};
Convert tcp_keepalive
C struct
To C# struct
.
[
System.Runtime.InteropServices.StructLayout
(
System.Runtime.InteropServices.LayoutKind.Explicit
)
]
unsafe struct TcpKeepAlive
{
[System.Runtime.InteropServices.FieldOffset(0)]
[
System.Runtime.InteropServices.MarshalAs
(
System.Runtime.InteropServices.UnmanagedType.ByValArray,
SizeConst = 12
)
]
public fixed byte Bytes[12];
[System.Runtime.InteropServices.FieldOffset(0)]
public uint On_Off;
[System.Runtime.InteropServices.FieldOffset(4)]
public uint KeepaLiveTime;
[System.Runtime.InteropServices.FieldOffset(8)]
public uint KeepaLiveInterval;
}
public int SetKeepAliveValues
(
System.Net.Sockets.Socket Socket,
bool On_Off,
uint KeepaLiveTime,
uint KeepaLiveInterval
)
{
int Result = -1;
unsafe
{
TcpKeepAlive KeepAliveValues = new TcpKeepAlive();
KeepAliveValues.On_Off = Convert.ToUInt32(On_Off);
KeepAliveValues.KeepaLiveTime = KeepaLiveTime;
KeepAliveValues.KeepaLiveInterval = KeepaLiveInterval;
byte[] InValue = new byte[12];
for (int I = 0; I < 12; I++)
InValue[I] = KeepAliveValues.Bytes[I];
Result = Socket.IOControl(IOControlCode.KeepAliveValues, InValue, null);
}
return Result;
}
To call method:
System.Net.Sockets.Socket Socket = new System.Net.Sockets.Socket
(
System.Net.Sockets.AddressFamily.InterNetwork,
System.Net.Sockets.SocketType.Stream,
System.Net.Sockets.ProtocolType.Tcp
);
SetKeepAliveValues(Socket, true, 36000000, 1000);
History
- 12th October, 2010: Initial post