Detecting and terminating aborted TCP/IP connections

Figure 1: Chat Server and Chat Client

Environment: VC5 SP3, NT4 SP3

When one side of the TCP-IP connection goes down abruptly without notifying the other end, the other end is left hanging. This is especially important for a server handling hundreds of connections. For such a server, even a single hanging socket is tantamount to wasting precious resources. Winsock does not provide a function which directly checks for abrupt termination of the TCP/IP connection at the other end.
The function HasConnectionDropped checks if the other end of the socket is still connected.
The pseudo code is:

[1] Check if the socket is readable.
[2] If yes, peek at the incoming data.
[3] Check the return values, error values to see if the network connection is still up.

It is important that we just peek at the incoming data. The MSG_PEEK flag does just that. The data is copied into the buffer but is not removed from the input queue. Thus we ensure that we do not disturb the functionality of the system.
We check the error values in case the recv call returns an error. Note that, if the recv call returns 0, it signifies a graceful disconnect from the other side. Hence, we consider a 0 return value as an indication of dropped connection.

As an example, consider the ChatServer and Chatter client example from MSDN. Communication between the client and server is via CMsg objects. A CMsg object contains two members:
m_bClose: To signify that the connection is being closed.
m_strText: The text to be posted on to the chat server.

In case of a normal termination, the client sends a message with m_bClose set to TRUE. The server closes down it's end of the connection on receiving this message and sends a close message to the client. The client closes down it's end after receiving this message.
So far so good. However, if the client terminates abruptly without sending the close message, the corresponding end at the server is never closed until the server shuts down.

I have modified the examples to illustrate the use of the HasConnectionDropped function.

On the server side, the menu handler for the menu item "Check Connections" iterates over the list of client connections to check if all connections are still up. Any client sockets for dropped connections are flushed out.

On the client side, the menu handler for the menu item "Kill myself" kills the client without giving it a chance to send a "Close" message to the server.

To run the demo:

[1] Start the server.

[2] Start one or more clients.

[3] Kill one (or more) client(s) by clicking "Kill myself" menu item. Note that, a message saying "xyz has left the discussion" does not appear on the board. We do have a hanging connection here!

[4] Click on "Check connections". A messagebox pops up showing the number of connections that were closed because they were dropped from the other side.

Note: I have written the function HasConnectionDropped to be a member of the CClientSocket (which depends upon the CSocket MFC class) to illustrate this technique. However the function does not depend on any CSocket/MFC/Windows functionality. Basic Winsock functions select and recv are used. Hence one can easily adapt this function to work in a non-MFC raw Winsock environment. The only change that has to be made is to accept the socket handle as a function parameter. (instead of as a member variable as in the present case)



BOOL CClientSocket::HasConnectionDropped( void )
{
	BOOL bConnDropped = FALSE;
	INT iRet = 0;
	BOOL bOK = TRUE;
	
	struct timeval timeout = { 0, 0 };
	fd_set readSocketSet;
	
	FD_ZERO( &readSocketSet );
	FD_SET( m_hSocket, &readSocketSet );
	
	iRet = ::select( 0, &readSocketSet, NULL, NULL, &timeout );
	bOK = ( iRet > 0 );
	
	if( bOK )
	{
		bOK = FD_ISSET( m_hSocket, &readSocketSet );
	}
	
	if( bOK )
	{
		CHAR szBuffer[1] = "";
		iRet = ::recv( m_hSocket, szBuffer, 1, MSG_PEEK );
		bOK = ( iRet > 0 );
		if( !bOK )
		{
			INT iError = ::WSAGetLastError();
			bConnDropped = ( ( iError == WSAENETRESET ) ||
				( iError == WSAECONNABORTED ) ||
				( iError == WSAECONNRESET ) ||
				( iError == WSAEINVAL ) ||
				( iRet == 0 ) ); //Graceful disconnect from other side.
		}
	}
	
    return( bConnDropped );
}


Downloads

Download demo project - 6 Kb


Comments

  • POVAD lBo yyfx

    Posted by ILHEOMrwcF on 11/16/2012 07:58pm

    buy soma online soma drug definition - soma carisoprodol uses

    Reply
  • Won't work is network prematurely dies

    Posted by menih on 08/20/2004 04:55pm

    If server prematurly is taken out of the network, exacly at the time where the client is in recv() call (waiting for server response), the client will hang forever, since no one tells it that server is not there anymore. The OS is not doing a good job noticing that the socket is gone. Actually it is quite happy and listing the socket is valid and healthy (viewed by sysinternals TCPView)

    Reply
  • not a easy thing

    Posted by Legacy on 09/24/2003 12:00am

    Originally posted by: andrew

    according to my experience,it is not so easy for the application to handle the tcpip connection state.i have encountered the following issues/scernaro,
    1.i am using Asynsocket sometimes.on windows nt,i found the onclose() can not be called immediately if i disconnected the cable.only after 5 to 10 minutes,onclose() can be called.
    while on windows 2000,onclose() can be called immediately.
    2.i found something interesting but quited confused.
    i telnet to some telnet server,log on,and execute "ls",i get the file list.
    then i disconnect the network cable,2 seconds later i resume the network cable.
    after that,i execute again,it is working!i get the file list again.
    so in the application,if i detect the connection state using ping machnish,in case of issue 2,we can imagine what will happen.
    please kindly suggest regarding those issues.
    thank u.

    Reply
  • FD_ISSET() seems unnecessary

    Posted by Legacy on 01/13/2003 12:00am

    Originally posted by: john seeker

    if( bOK )
    {
    bOK = FD_ISSET( m_hSocket, &readSocketSet );
    }

    Reply
  • Way to detect a dropped connection

    Posted by Legacy on 10/24/2002 12:00am

    Originally posted by: Dan W.

    Is the only way to really detect a dropped client connection is to send data every so often and check the return code? Why doesn't the SO_KEEPALIVE option work? recv should fail when a keepalive message is not sent in the lower level. Any other suggestions to do this more cleanly than sending out blank packets every so often.

    Reply
  • Where should I start

    Posted by Legacy on 09/04/2002 12:00am

    Originally posted by: Kevin Nguyen

    Hi there,
    I read through your document and really like it. I am having a project which is implementing a chat server/client thing. I have no idea where to start since I have never do socket programming before. Any help would be appriciated.

    Hope to hear from you soon

    Reply
  • how to connect a webcam to the chat application

    Posted by Legacy on 07/25/2002 12:00am

    Originally posted by: krishna k

    hi,
    i need some ideas as to how to add a web cam to the chat application , if any one has got some idea as to is there any function or some api that i can include to get the web cam connectivity.
    my email id is . krishnak_1977@indiatimes.com.
    bye..

    Reply
  • NICE

    Posted by Legacy on 06/24/2002 12:00am

    Originally posted by: IGO

    GOOD work

    Reply
  • CAsyncSocket dropped...

    Posted by Legacy on 05/12/2002 12:00am

    Originally posted by: J

    I'm using CAsyncSocket and when the connection is dropped,
    the inplementation does'nt call OnClose()
    It get's called when i Try Send()

    How to prevent this??

    Reply
  • For blocking socket,how can the server auto-detect the client is abnormally shut down?

    Posted by Legacy on 01/26/2002 12:00am

    Originally posted by: kdh

    Hi,all
    For blocking socket,how can the server auto-detect the client is abnormally shut down?If the client is suddenly offline or the power is turned off,how can hte server know that?

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • VMware vCloud® Government Service provided by Carpathia® is an enterprise-class hybrid cloud service that delivers the tried and tested VMware capabilities widely used by government organizations today, with the added security and compliance assurance of FedRAMP authorization. The hybrid cloud is becoming more and more prevalent – in fact, nearly three-fourths of large enterprises expect to have hybrid deployments by 2015, according to a recent Gartner analyst report. Learn about the benefits of …

Most Popular Programming Stories

More for Developers

RSS Feeds