Skip to content

Implement portable support for TCP_KEEPCNT, TCP_KEEPIDLE and TCP_KEEPINTVL socket options #24041

@hexawyz

Description

@hexawyz

Allow for configuring TCP Keepalive in a portable manner.

Rationale

TCP Keepalive is an optional feature of TCP that is implemented in most widely used OSes and the feature can already be enabled in .NET by using SocketOptionName.KeepAlive.
However, it is not possible, as of now, to set the various keepalive options using a standard .NET API.

Most platforms, more than simply allowing TCP keepalive, provide a subset of the following three options:

  • Keepalive Time
  • Keepalive Interval
  • Keepalive Retry Count

Since Windows 2000, it has been possible to set both Keepalive Time and Keepalive Interval by using SIO_KEEPALIVE_VALS with Winsock IOCTL (Exposed via Socket.IOControl and IOControlCode.KeepAliveValues in .NET)
Under Linux, TCP Keepalive can be configured with setsockopt under the SOL_TCP level. The allowed parameters are TCP_KEEPCNT, TCP_KEEPIDLE and TCP_KEEPINTVL.

It seems OSX also has some good support for the feature since OSX Lion, only using slightly different names than Linux:
https://lists.apple.com/archives/macnetworkprog/2012/Jul/msg00005.html

From the docs, since Windows 10 version 1703 and 1709, settings that are code-compatible with Linux and OSX were introduced:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms738596(v=vs.85).aspx

As explained in https://github.com/dotnet/corefx/issues/14237, it is impossible today to configure TCP keepalive on platforms other than Windows, where Socket.IOControl can do the trick.

Proposed API

enum SocketOptionName
{
//…
	#region SocketOptionLevel.Tcp
//…
	// TCP KeepAlive options
	TcpKeepAliveRetryCount = 16, // TCP_KEEPCNT value from Ws2ipdef.h
	TcpKeepAliveTime = 3, // TCP_KEEPIDLE = TCP_KEEPALIVE value from Ws2ipdef.h
	TcpKeepAliveInterval = 17, // TCP_KEEPINTVL value from Ws2ipdef.h
	#endregion
//…
}

Example

void EnableKeepAlive(Socket socket, byte retryCount, int keepAliveTimeInSeconds, int keepAliveIntervalInSeconds)
{
	socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
	socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveRetryCount, (int)retryCount);
	socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, keepAliveTimeInSeconds);
	socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, keepAliveIntervalInSeconds);
}

Details

The PAL for each supported platform would translate the call to Socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAlive*, *) into the appropriate call for the platform.

  • On Linux, and OSX ≥ 10.7, .NET enumeration values would be translated to corresponding system values for setsockopt().
  • On Windows 10 version 1709 and newer, the flags would be transferred as-is to the underlying Winsock API, as they already are today.
  • Ideally, TcpKeepAliveTime and TcpKeepAliveInterval would be marshalled to socket.IOControl(IOControlCode.KeepAliveValues, KeepAliveValues, null) for previous versions of windows, while TcpKeepAliveRetryCount would be simply ignored.

⚠️ Beware that commonly used socket option names TCP_KEEPIDLE (or TCP_KEEPALIVE) and TCP_KEEPINTVL are expressed in seconds, while SIO_KEEPALIVE_VALS expresses durations in milliseconds.

Questions

The TCP keepalive feature being optional, it is not required that all platforms support it or provide any specific way of configuring the feature.

  • Should a call to a non supported TCP keepalive option throw an exception ?
  • How should a caller determine if a given option is indeed supported on the current platform ?
  • Should an additional socket property, similar to Socket.LingerState be also added (e.g. KeepAliveState of type KeepAliveOption), in order to group the various options and handle everything at one place ?
    • The feature could be used with something like socket.KeepAliveState = new KeepAliveOption(true, 15, 7200, 1)
    • This would also be more consistent with the way the feature is configured on legacy Windows system.

Metadata

Metadata

Labels

HackathonIssues picked for Hackathonapi-approvedAPI was approved in API review, it can be implementedarea-System.Net.Socketshelp wanted[up-for-grabs] Good issue for external contributors

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions