A simple check of the properties of this problem is not solved. The fact is that in the passive state, the TCP protocol does not transmit anything - and therefore there is no way to know in a reasonable time whether the client is still connected or something happened to it.
Only the active connection can determine the client's state - and there are two approaches here.
Approach the first - a ping.
The meaning of this approach is to allow the TCP driver to diagnose a disconnection. The TCP driver, in turn, can do this if one of three conditions is met:
- RST package arrived
- The ICMP packet came with an error message (I personally don’t know if these packets are used by common TCP drivers, just for completeness)
- The limit of attempts to send data has been exceeded.
The first two methods of detecting a disconnection are unreliable, so it remains to think about the third. In order to exceed the limit of attempts to send data, TCP must transmit this same data. So, you need to periodically write something to the socket. As long as data is written to the socket, a disconnection will be detected. But if the connection is idle, it makes sense to start periodically recording messages there that will be ignored by the other party. This is called, conditionally, a PING message.
This method is the easiest - just periodically write the timer to the socket, then everything will happen by itself.
Second approach - keepalive messages
The point of this approach is to determine the disconnection before the TCP driver can. For this purpose, a timer is introduced that counts the time from receiving the last byte through a socket. After each read from the socket, the timer starts counting again.
In this scheme, the client will be disconnected after a certain time after it is "silent". If this is undesirable for the client, it should periodically send "empty" messages that will be ignored by the server, but reset the disconnect timer. Such messages are called keepalive messages.
This method is more complicated than the past, because it requires timers on both sides of the connection.
About the combination of approaches. If it is necessary to check the status of the connection from both sides, then the option is possible when the server sends empty messages - and the client only accepts them. In this case, on the server it is enough to periodically write to the socket - and on the client you will need to do a break connection timer. Or vice versa. In this case, the same message will behave both as a ping message and as a keepalive message.
When using the same approach, empty packages will inevitably walk in both directions.
About the answers to the "ping" ("pongs"). On their own, “pongs” are not needed to test for disconnection - and without them, disconnection is perfectly detected. But pongs protect against another problem — some clients may (as a result of an error) put the connection to a half-open state when they can only read — but no longer send packets. If the server is not properly implemented, the connection may be permanently stuck in this state.
About replies to keepalive messages. By themselves, keepalive messages, if used in both directions, perfectly determine both the disconnection of the connection and its getting stuck in the "half-open" state. But the introduction of mandatory responses to keepalive messages allows the client and server to have different timer interval settings.