TCP Socket options

Hello everyone, I’m trying to create a TCP Telnet server on a SCM20260E
When a client is connected I need to configure the socket for quick disconnect detection.
Using C# these are the options needed:

tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
tcpClient.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, 5);
tcpClient.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, 1);
tcpClient.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveRetryCount, 3);

Some of these options do not exist in the assembly GHIElectronics.TinyCLR.Networking, specifically the last three options in the enum System.Net.Sockets.SocketOptionName.

However, looking at the original enumeration in C# here: SocketOptionName Enum (System.Net.Sockets) | Microsoft Learn

I came up with the following names that use the same value:

client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
// TypeOfService value is 3 same as TcpKeepAliveTime
client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TypeOfService, 5);
// BlockSource value is 17 same as TcpKeepAliveInterval
client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.BlockSource, 1);
// DropSourceMembership value is 16 same as TcpKeepAliveRetryCount
client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.DropSourceMembership, 3);

Will this work the same way?
Is it the recommended way to use it?

I get what you’re trying to do, but keep-alive might not be the best solution.

The way keep-alive works can vary depending on the platform. The timeout value can differ, and it’s usually measured in hours. I did a quick search and found a reference that said the timeout on Windows is two hours.

Years ago, I stopped using keep-alive to detect connection disruptions.

If the client closes the connection normally, the host will see the disconnection by the end of an outstanding read or an exception. Keep-alive strategies are needed when the client program closes before a socket close can be issued or the connection path has been disrupted. For example, the network cable has been pulled.

In most host-client TCP connections, I send a keep-alive message from each end periodically. If the connection is no longer viable, you’ll know within a few seconds.

You mentioned you wanted a Telnet connection. I’m not sure if you mean an implementation of the Telnet protocol. If so, you can send a Telnet query message periodically. This would be the keep-alive message.

Yes, I’m trying to do a very basic implementation of Telnet.
However, the main concern is that the system needs to stop within 10 to 15 seconds if no client is listening for any reason.

Start experimenting… I believe it can be done.

I agree with Mike here. Implement the keep alive yourself. I have a network interface that uses sockets directly, not the TcpClient/TcpHost, but its the same since your TcpClient.Client is a socket. I couple the receive/send time outs on the client socket with a periodic message. I send a message every 1 sec from the server to the client requesting some information that i am using to update a UI. If the Client doesn’t ACK the request in the send timeout, or the client doesn’t send something in the read timeout period, your Write() or Read() will throw an exception. If the client disconnects gracefully (meaning it sends a FIN), you’ll get an empty Read (i.e. it will return 0 bytes read). This lets you know the client left gracefully. This should give you the feedback you need, provided your keep alive interval is shorter than your 10-15s.

They way I’ve gotten it to work is polling for data every 10-100ms, and before I check for any data bytes I run the code below. This allows me to immediately detect if a connection has been broken, client or server (you may need to adjust the polling microseconds).

//Check the connection
if (_remoteSocket == null || (_remoteSocket.Poll(5000, SelectMode.SelectRead) && _remoteSocket.Available == 0))
{
    Logger.LogMessage(Logger.Level.Info, _controllerId, $"{(IsHost ? "Client" : "Server")} disconnected...");
    CloseTcpConnection(true);
    return;
}