Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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);
            }
        }
    }
like image 670
TEDSON Avatar asked Mar 11 '23 02:03

TEDSON


2 Answers

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.

like image 53
d3dave Avatar answered Mar 23 '23 03:03

d3dave


It is because cli.GetStream(); does not create a new stream every time you call it, there is a single stream for the connection and every call to cli.GetStream(); returns the same stream object. When you dispose of that shared stream that signals to the TcpClient you are done and it marks the TcpClient disconnected.

like image 20
Scott Chamberlain Avatar answered Mar 23 '23 02:03

Scott Chamberlain