繁体   English   中英

Socket 的扩展方法“ReceiveAsync”的内存泄漏!

[英]Memory leak of the Socket's extension method 'ReceiveAsync'!

我有一个基于异步Socket的长时间运行的服务程序。 当其他设备检测到它的健康状况(短时间 TCP 端口连接和断开连接)时,它的内存使用量会随着时间的推移而不断增加。 我怀疑这种类型的 TCP 连接的一些内存没有被释放。 于是我做了一个简单的验证程序:

class Program
{
    static void Main(string[] args) => new Program().Start(args[0] == "server");

    private void Start(bool bStartServer)
    {
        if (bStartServer)
        {
            TcpListener tlToClient = TcpListener.Create(2868);
            tlToClient.Start();
            DoClientService(tlToClient);
            System.Console.WriteLine("start on port 2868...");
            for (int i = 0; i < 10; i++)
            {
                Console.ReadLine();
                GC.Collect();
            }
        }
        else
        {
            for (int i = 0; i < 50000; i++)
            {
                Socket s = new Socket(SocketType.Stream, ProtocolType.Tcp);
                s.Connect("127.0.0.1", 2868);
                s.Shutdown(SocketShutdown.Both);
                s.Close();
            }
            System.Console.WriteLine("all done");
            Console.ReadLine();
        }
    }

    static async Task DoClientService(TcpListener tlToClient)
    {
        while (true)
            Receive(await tlToClient.AcceptSocketAsync().ConfigureAwait(false));
    }

    static async Task Receive(Socket socket)
    {
        while (true)
        {
            await Task.Delay(50).ConfigureAwait(false);
            var read = await socket.ReceiveAsync(new ArraySegment<byte>(new byte[8192], 0, 8192), SocketFlags.None).ConfigureAwait(false);
            if (read == 0)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Dispose();
                return;
            }
        }
    }
}

如代码所示,服务端监听2868端口后,测试客户端会继续发起50000个TCP连接,连接成功后关闭这些连接。 当服务器接收缓冲区设置为8192时,测试结束后服务器将占用800MB内存。

怀疑是Socket的扩展方法ReceiveAsync的内部实现存在bug,导致reveive缓冲区无法释放。

代码已经简化,只会测试内存泄漏问题。

任何帮助,将不胜感激!

您应该创建一个缓冲区并重复使用它。 垃圾收集不是激进的,这可以解释泄漏。 更具体地说,这一行var Buffer = new ArraySegment<byte>(new byte[8192], 0, 8192);

应该在你的 while 循环之外,它应该被传递到 ReciveAsync。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM