Let's say I'm running a simple server and have accept()
ed a connection from a client.
What is the best way to tell when the client has disconnected? Normally, a client is supposed to send a close command, but what if it disconnects manually or loses network connection altogether? How can the server detect or handle this?
TCP does have acknowledgments for data, so when one side sends data to the other side, it will receive an acknowledgment if the connection is still active (or an error if it is not). Thus, broken connections can be detected by sending out data.
Enter "telnet + IP address or hostname + port number" (e.g., telnet www.example.com 1723 or telnet 10.17.xxx.xxx 5000) to run the telnet command in Command Prompt and test the TCP port status. If the port is open, only a cursor will show. If the port is closed, a message will say Connect failed.
The common way of terminating a TCP connection is by using the TCP header's FIN flag. This mechanism allows each host to release its own side of the connection individually. Suppose that the client application decides it wants to close the connection. (Note that the server could also choose to close the connection).
There are three ways a TCP connection is closed: The client initiates closing the connection by sending a FIN packet to the server. The server initiates closing the connection by sending a FIN packet to the client. Both client and server initiate closing the connection.
In TCP there is only one way to detect an orderly disconnect, and that is by getting zero as a return value from read()/recv()/recvXXX()
when reading.
There is also only one reliable way to detect a broken connection: by writing to it. After enough writes to a broken connection, TCP will have done enough retries and timeouts to know that it's broken and will eventually cause write()/send()/sendXXX()
to return -1 with an errno/WSAGetLastError()
value of ECONNRESET,
or in some cases 'connection timed out'. Note that the latter is different from 'connect timeout', which can occur in the connect phase.
You should also set a reasonable read timeout, and drop connections that fail it.
The answer here about ioctl()
and FIONREAD
is compete nonsense. All that does is tell you how many bytes are presently in the socket receive buffer, available to be read without blocking. If a client doesn't send you anything for five minutes that doesn't constitute a disconnect, but it does cause FIONREAD
to be zero. Not the same thing: not even close.
To expand on this a bit more:
If you are running a server you either need to use TCP_KEEPALIVE to monitor the client connections, or do something similar yourself, or have knowledge about the data/protocol that you are running over the connection.
Basically, if the connection gets killed (i.e. not properly closed) then the server won't notice until it tries to write something to the client, which is what the keepalive achieves for you. Alternatively, if you know the protocol better, you could just disconnect on an inactivity timeout anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With