The TcpClient Close method does not close the underlying TCP connection (821625)



The information in this article applies to:

  • Microsoft .NET Framework 1.1
  • Microsoft .NET Framework 1.0
  • Microsoft Visual C# .NET (2003)
  • Microsoft Visual C# .NET (2002)

This article refers to the following Microsoft .NET Framework Class Library namespaces:
  • System.Net
  • System.Net.Sockets

SYMPTOMS

When you call the TcpClient Close method, you expect the underlying TCP connection to be closed as described in the "TcpClient.Close Method" topic of the .NET Framework Class Library documentation. For more information, visit the following Microsoft Web site:

RESOLUTION

To resolve this problem, close the associated NetworkStream object that the TcpClient GetStream method returns.

MORE INFORMATION

Steps to reproduce the problem

  1. In a text editor such as Notepad, paste the following sample code.
    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    
    class Server
    {
    	static void Main(string[] args)
    	{
    		try
    		{
    			const int portNumber = 10000;
    			TcpListener tcpListener = new TcpListener(IPAddress.Loopback, portNumber);
    
    			tcpListener.Start();
    
    			Console.WriteLine("Waiting for a connection....");
    
    			//Accept the pending client connection, and then return a TcpClient that is initialized for communication.
    			TcpClient tcpClient = tcpListener.AcceptTcpClient();
    			Console.WriteLine("Connection accepted.");
    
    			NetworkStream networkStream = tcpClient.GetStream();
    
    			string responseString = "You have successfully connected to me\n";
    
    			Byte[] sendBytes = Encoding.ASCII.GetBytes(responseString.ToCharArray());
    			networkStream.Write(sendBytes, 0, sendBytes.Length);
    
    			Console.Write("Message Sent /> : " + responseString);
    
    			//Close networkStream and TcpClient.
    			//networkStream.Close();
    			tcpClient.Close();
    
    			//Wait until you can see that the connection is closed in the client.
    			Console.ReadLine();
                                
    			//Close the listener.
    			tcpListener.Stop();
    
    		}
    		catch (Exception e) 
    		{
    			Console.WriteLine(e.ToString());
    		}   
    	}
    }
  2. Save the file as Server.cs.
  3. Click Start, point to Programs, point to Microsoft Visual Studio .NET (for Microsoft Visual Studio .NET 2002) or Microsoft Visual Studio .NET 2003, point to Visual Studio .NET Tools, and then click Visual Studio .NET Command Prompt or Visual Studio .NET 2003 Command Prompt.
  4. At the command prompt, type the following command, and then press ENTER to compile Server.cs:

    csc server.cs

  5. At the command prompt, type the following command, and then press ENTER:

    start server.exe

  6. At the command prompt, type the following command, and then press ENTER:

    netstat -p tcp -a

    Notice that a TCP connection is opened at port 10000 and the connection is in the LISTENING state.
  7. In a text editor such as Notepad, paste the following sample code.
    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    
    class Client
    {
    	static void Main(string[] args)
    	{
    		try
    		{
    			TcpClient tcpClient = new TcpClient();
    		
    			tcpClient.Connect(IPAddress.Loopback, 10000);
    			NetworkStream networkStream = tcpClient.GetStream();
    
    			if(networkStream.CanWrite && networkStream.CanRead)
    			{
    				// Reads the NetworkStream to a byte buffer.
    				byte[] bytes = new byte[38];
    				networkStream.Read(bytes, 0, bytes.Length);
    				
    				// Returns to the console the data that is received from the host.
    				string returndata = Encoding.ASCII.GetString(bytes);
    				Console.Write("This is what the host returned to you: " + returndata.TrimEnd(new char[] {' '}));
    				Console.ReadLine();
    				networkStream.Close();
    				tcpClient.Close();
    			}
    		}
    		catch (Exception e ) 
    		{
    			Console.WriteLine(e.ToString());
    		}
    	}
    }
  8. Save the file as Client.cs.
  9. At the command prompt, type the following command, and then press ENTER to build Client.cs:

    csc client.cs

  10. At the command prompt, type the following command, and then press ENTER:

    start client.exe

  11. At the command prompt, type the following command, and then press ENTER:

    netstat -p tcp -a

    Notice that a TCP connection is opened, and that the connection is in the ESTABLISHED state.

    Because the connection on the server side is closed, the server side socket connection should be in the FIN_WAIT_2 state, and the client side socket connection should be in the CLOSE_WAIT state. This behavior is described in RFC 793 - "Transmission Control Protocol Darpa Internet Program Protocol Specification."
  12. Change the code in step 1 by uncommenting the following line:
    //networkStream.Close();
    Repeat steps 3 through 9.

    Notice that the server side socket connection is in the FIN_WAIT_2 state, and the client side socket connection is in the CLOSE_WAIT state. This behavior occurs because the connection is closed on the server side.

REFERENCES

For more information about the TcpClient class, visit the following Microsoft Web site:

Modification Type:MajorLast Reviewed:1/26/2006
Keywords:KbClientServer kbAPI kbProgramming kbprb KB821625 kbAudDeveloper