Search code examples
c#usingnetworkstreamdisconnect

Why disposing NetworkStream disconnects client


When the following bare bones code is sending or receiving data, the client becomes disconnected.

It was my understanding that a using block disposes the object it creates, ie the NetworkStream object, but why does the TcpClient Socket disconnect?

The console output is... True False

class Program
    {
        static void Main(string[] args)
        {
            Console.Title = "Client";

            Process p = Process.Start(@"C:\Users\Teddy\Documents\visual studio 2015\code\TesyingNetworkStream\Server\bin\Debug\server.exe");
            Thread.Sleep(1000);

            IPEndPoint EP = new IPEndPoint(
                    IPAddress.Parse("192.168.1.10"), 4000
                    );

            TcpClient cli = new TcpClient();
            cli.Connect(EP);

            UseClient(cli);

            Console.ReadLine();
            p.Kill();
            p.Close();
        }

        private static void UseClient(TcpClient cli)
        {
            using (NetworkStream ns = cli.GetStream())
            {
                Console.WriteLine(cli.Connected);//True
            }
            Console.WriteLine(cli.Connected);//False
        }
    }

Here is server code if it matters.

class Program2
    {
        static void Main(string[] args)
        {
            Console.Title = "Server";

            TcpListener lis = new TcpListener(
                new IPEndPoint(
                    IPAddress.Any, 4000
                    ));

            lis.Start();

            lis.AcceptTcpClient();

            while (true)
            {
                Thread.Sleep(10);
            }
        }
    }

Solution

  • Here's the GetStream() function implementation (from .NET framework source):

    public NetworkStream GetStream() {
        if (m_CleanedUp){
            throw new ObjectDisposedException(this.GetType().FullName);
        }
        if (!Client.Connected) {
            throw new InvalidOperationException(SR.GetString(SR.net_notconnected));
        }
        if (m_DataStream == null) {
            m_DataStream = new NetworkStream(Client, true);
        }
        return m_DataStream;
    }
    

    Note the true in the call to the NetworkStream constructor. This is the ownsSocket parameter. From MSDN:

    If the value of ownsSocket parameter is true, the NetworkStream takes ownership of the underlying Socket, and calling the Close method also closes the underlying Socket.

    NetworkStream's Dispose implementation Close's the stream, which then closes the socket.