为什么配置 NetworkStream 会断开客户端

Why disposing NetworkStream disconnects client

当以下基本代码发送或接收数据时,客户端断开连接。

据我了解,using 块处理它创建的对象,即 NetworkStream 对象,但为什么 TcpClient Socket 会断开连接?

控制台输出是... 真的 假

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
        }
    }

如果重要的话,这里是服务器代码。

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);
            }
        }
    }

这是因为 cli.GetStream(); 不会在您每次调用它时都创建一个新流,连接只有一个流,并且每次调用 cli.GetStream(); returns 相同的流目的。当您处理向 TcpClient 发送信号的共享流时,您已完成并标记 TcpClient 已断开连接。

这是 GetStream() 函数的实现(来自 .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;
}

请注意 NetworkStream 构造函数调用中的 true。这是 ownsSocket 参数。来自 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.

NetworkStreamDispose 实现 Close 的流,然后关闭套接字。