none
How to properly close a Socket connection RRS feed

  • Question

  • My C# application communicates to a data acquisition system using a TCP/IP connection.  I use the Socket class to manage the connection to the communicating peer, which act as the listener in the Socket connection.  A connection is made, a command sent to begin acquisition, and data is then received - 1000 1K messages every second.  When acquisition is to be stopped, a stop command is sent and a wait for 2 seconds, to allow any extraneous messages to be received.  Then, the socket is closed using this method:

    private Socket _socket;

    ...

    public void Close() { if ((_socket == null) || (!_socket.Connected)) { throw new InvalidOperationException("Attempt to close a socket which is not connected"); } _socket.Shutdown(SocketShutdown.Both); _socket.Close(); _socket = null;

    About half the time, the communicating peer does not detect the connection is closed.  Upon closer examination of the network traffic using WireShark, I found that when the connection is closed using this code, a RST packets was sometimes sent, and other times a FIN packet is sent.  When the RST packet is sent, the other side immediately recognizes the socket is closed.  When the FIN packet is used after Close(), it take one minute before some kind of timeout occurs and the connection finally closed by the peer.

    Is there another way to close a connection on a socket that I should use?

    Thursday, December 15, 2016 5:47 PM

All replies

  • Hi John,

    >> I found that when the connection is closed using this code, a RST packets was sometimes sent, and other times a FIN packet is sent.  When the RST packet is sent, the other side immediately recognizes the socket is closed.   When the FIN packet is used after Close(), it take one minute before some kind of timeout occurs and the connection finally closed by the peer.

    A FIN says no more data from the sender. The user will send a FIN and will wait until its own FIN is acknowledged whereupon it deletes the connection. If an ACK is not forthcoming, after the user timeout the connection is aborted and the user is told.

    An RST says reset the connection. It must be sent whenever a segment arrives which apparently is not intended for the current connection.Or in other words,
    FIN says, "I finished talking to you, but I'll still listen to everything you have to say until you're done" (Wait for an ACK)
    RST says, "There is no conversation. I am resetting the connection!"

    Based on your description, it is an expect result.

    Best regards,

    Kristin


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    • Edited by Kristin Xie Friday, December 16, 2016 5:36 AM
    Friday, December 16, 2016 3:10 AM
  • Thank you for the explanation about FIN and RST.  However, it still does not answer the question.  I use the same two methods every time I close the connection:

    _socket.Shutdown(SocketShutdown.Both);
    _socket.Close();

    This is the data acquisition application.  Roughly half the time, the side that closes the socket this way emits a FIN, the other half of the time it emits a RST.

    Having said all that, I took a closer look at the receiving side code, another .Net application.  The receive code is as follows:

    private void ReceiveWorker() {
    	byte[] receiveBuffer = new byte[2000];
    	try {
    	        while (_socket.Connected) {
    			int numReceived = _socket.Receive(receiveBuffer);
    			if (numReceived <= 0) {
    				break;
    			}
    			if (DataReceived != null) {
    				byte[] buffer = new byte[numReceived];
    				Array.Copy(receiveBuffer, buffer, numReceived);
    				DataReceived(this, new ReceivedDataEventArgs(buffer));
    			}
    		}
    	}
    	catch (ObjectDisposedException) {
    		if (DataReceived != null) {
    			DataReceived(this, new ReceivedDataEventArgs(ReceiveStatus.Closed));
    		}
    	}
    	catch (Exception ex) {
    		if (DataReceived != null) {
    			SocketException sockException = ex as SocketException;
    			if ((sockException != null) && (sockException.ErrorCode == WSACONNRESET)) {
    				DataReceived(this, new ReceivedDataEventArgs(ReceiveStatus.Closed));
    			}
    			else {
    				DataReceived(this, new ReceivedDataEventArgs(ex));
    			}
    		}
    	}
    	finally {
    		Exception ex = _runningTask.Exception;
    		if (ex != null) {
    			Console.WriteLine("ReceiveWorker exception: {0} ", ex.Message);
    		}
    	}
    }
    

    When the DataReceived event is raised, only when the status is ReceiveStatus.Closed do I close the socket connection.  This only happens if _socket.Receive() throws an ObjectDisposedException or a SocketException with ErrorCode WSACONNRESET.  Obviously, the latter is happening when RST is sent on the socket close by the other side.  I will look closer at other ways to detect the FIN instead of the RST.

    However, this still doesn't explain why the one side sometimes sends RST and sometimes FIN when I use the same exact code to close the socket every time.

    Friday, December 16, 2016 3:25 PM
  • Hi John,

    I'm not expert in TCP protocol, I found some trouble shooting ideas that worth trying
     1. Check the state of you tcp connection to see why your connection had to wait a time out to close with a  Fin packet. You can refer this article to check it. https://support.microsoft.com/en-us/kb/137984
     2. Use other method to test the connection state and close the connection form client side.
     http://stackoverflow.com/questions/2661764/how-to-check-if-a-socket-is-connected-disconnected-in-c
     3. check the following best practise to close the socket connection at both client and server side https://msdn.microsoft.com/en-us/library/windows/desktop/ms738547%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
    http://stackoverflow.com/questions/15321094/tcp-server-and-client-c-sharp-best-practice

    Best wishes!

    Kristin


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, December 19, 2016 2:18 PM