Detecting TCP Client Disconnect

C++SocketsTcp

C++ Problem Overview


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?

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

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.

Solution 3 - C++

If you're using overlapped (i.e. asynchronous) I/O with completion routines or completion ports, you will be notified immediately (assuming you have an outstanding read) when the client side closes the connection.

Solution 4 - C++

Try looking for EPOLLHUP or EPOLLERR. https://stackoverflow.com/questions/6434305/how-do-i-check-client-connection-is-still-alive

Reading and looking for 0 will work in some cases, but not all.

Solution 5 - C++

TCP has "open" and a "close" procedures in the protocol. Once "opened", a connection is held until "closed". But there are lots of things that can stop the data flow abnormally. That being said, the techniques to determine if it is possible to use a link are highly dependent on the layers of software between the protocol and the application program. The ones mentioned above focus on a programmer attempting to use a socket in a non-invasive way (read or write 0 bytes) are perhaps the most common. Some layers in libraries will supply the "polling" for a programmer. For example Win32 asych (delayed) calls can Start a read that will return with no errors and 0 bytes to signal a socket that cannot be read any more (presumably a TCP FIN procedure). Other environments might use "events" as defined in their wrapping layers. There is no single answer to this question. The mechanism to detect when a socket cannot be used and should be closed depends on the wrappers supplied in the libraries. It is also worthy to note that sockets themselves can be reused by layers below an application library so it is wise to figure out how your environment deals with the Berkley Sockets interface.

Solution 6 - C++

It's really easy to do: reliable and not messy:

> Try > Clients.Client.Send(BufferByte) > Catch verror As Exception > BufferString = verror.ToString > End Try > If BufferString <> "" Then > EventLog.Text &= "User disconnected: " + vbNewLine > Clients.Close() > End If

Solution 7 - C++

I toyed with a few solutions but this one seems to work best for detecting host and/or client disconnection in Windows. It is for non-blocking sockets, and derived from IBM's example.

char buf;
int length=recv(socket, &buf, 0, 0);
int nError=WSAGetLastError();
if(nError!=WSAEWOULDBLOCK&&nError!=0){
    return 0;
}	
if (nError==0){
    if (length==0) return 0;
}

Solution 8 - C++

The return value of receive will be -1 if connection is lost else it will be size of buffer.

void ReceiveStream(void *threadid)
{
	while(true)
	{
		while(ch==0)
		{
			char buffer[1024];
			int newData;
			newData = recv(thisSocket, buffer, sizeof(buffer), 0);
			if(newData>=0)
			{
				std::cout << buffer << std::endl;
			}
			else
			{
				std::cout << "Client disconnected" << std::endl;
				if (thisSocket)
				{
					#ifdef WIN32
						closesocket(thisSocket);
						WSACleanup();
					#endif
					#ifdef LINUX
						close(thisSocket);
					#endif
				}
				break;
			}
		}
		ch = 1;
		StartSocket();
	}
}

Solution 9 - C++

select (with the read mask set) will return with the handle signalled, but when you use ioctl* to check the number of bytes pending to be read, it will be zero. This is a sign that the socket has been disconnected.

This is a great discussion on the various methods of checking that the client has disconnected: Stephen Cleary, Detection of Half-Open (Dropped) Connections.

* for Windows use ioctlsocket.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZxaosView Question on Stackoverflow
Solution 1 - C++user207421View Answer on Stackoverflow
Solution 2 - C++Peter JefferyView Answer on Stackoverflow
Solution 3 - C++Graeme PerrowView Answer on Stackoverflow
Solution 4 - C++Trade-Ideas PhilipView Answer on Stackoverflow
Solution 5 - C++jlpaytonView Answer on Stackoverflow
Solution 6 - C++DavidView Answer on Stackoverflow
Solution 7 - C++GalleonView Answer on Stackoverflow
Solution 8 - C++Anand PaulView Answer on Stackoverflow
Solution 9 - C++sepView Answer on Stackoverflow