Generally speaking, you cannot affirmatively detect an uncleanly-disconnected client.
Edit: that is, there is no general-purpose are_you_still_there()
function, and there is no way to implement one that you can rely upon always to swiftly deliver "no" responses with neither false negatives nor false positives.
If you are using a connectionless network protocol (i.e. UDP), then you cannot affirmatively detect that a client has permanently disappeared at all.
Edit: TCP provides for automatic data retransmission in the event that the receiver does not acknowledge receipt. Multiple retransmissions of the same data are possible, in which case the timeout between (re)transmissions increases exponentially. After a threshold number of retransmissions or a threshold retransmission timeout is reached without an acknowledgement, a TCP subsystem will deem the connection broken, but this may take several or even tens of minutes, depending on the local protocol implementation and parameters.
You can rely on a read()
to signal an error if the TCP implementation detects connection breakage, either by timeout or by the remote peer forcibly severing the connection. It may be tricky or impossible, however, to ensure that such an error is delivered to the application in a "timely" manner if your notion of "timely" is much different from the TCP implementation's.
One generally deals with this problem by employing [edit: application-level] timeouts to judge when to release resources devoted to servicing a client, or possibly via a higher-level protocol that provides for a heartbeat signal or the equivalent (which basically still boils down to timeouts).
Edited to add: implementation of an "are you there" message in the application-layer protocol can provide a means to solicit a response from the peer, so as to be able to measure timeout and/or detect connection closure during times when the connection otherwise would be idle. Inasmuch as this more or less amounts to a means for the local machine to solicit a heartbeat from the remote peer, it's similar to what you already have.
On the other hand, it does provide a framework wherein the local machine can attempt to send unsolicited messages to the peer without interfering with the application. That way, if the TCP implementation has marked the connection closed, whether because of TCP-level timeout or because the other end closed it then the local machine will be notified of the closure at that time.