【问题标题】:Memory Leak in C# Socket applicationC# Socket 应用程序中的内存泄漏
【发布时间】:2012-09-16 03:41:24
【问题描述】:

我正在尝试编写一个服务器应用程序,该应用程序正在侦听特定端口并等待设备访问该端口。设备每 30 秒连接一次设备连接后,设备会发送其 MAC 地址。但问题是内存不断增加并且永远不会释放。

class Server
{
    Object threadLock = new Object();
    bool stopListening = false;
    Socket clientSocket = null;

    private  void StartDeviceListener()
    {

        try
        {
            // create the socket
            clientSocket = new Socket(AddressFamily.InterNetwork,
                                             SocketType.Stream,
                                             ProtocolType.Tcp);

            // bind the listening socket to the port
            IPEndPoint ep1 = new IPEndPoint(IPAddress.Any, 60000);
            clientSocket.LingerState = new LingerOption(false, 0);

            clientSocket.Bind(ep1);
            clientSocket.Listen(10); //Waiting for Devices to connect.

            do
            {
                // start listening
                Console.WriteLine("Waiting for device connection on {0}....", 60000);
                Socket deviceSocket = clientSocket.Accept();
                //Console.WriteLine(deviceSocket.
                #region ThreadPool

                // ThreadPool.QueueUserWorkItem(ProcessRequest, (Object)deviceSocket);
                Thread ts = new Thread(ProcessRequest);
                ts.IsBackground = true;
                ts.Start((Object)deviceSocket);
                ts.Join();
                #endregion
            } while (!stopListening);

        }
        catch (Exception ex)
        {
            Console.WriteLine("exception... : " + ex.Message);
            StartDeviceListener();
        }

        finally
        {
            if (clientSocket != null) { clientSocket.Close(); clientSocket = null; }
        }

    }

    public void Stop()
    {
        try
        {
            stopListening = true;
            if (clientSocket != null)
            {
                clientSocket.Disconnect(false);
                clientSocket = null;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("exception : " + ex.Message);
        }
    }


    void ProcessRequest(Object args)
    {
        using (Socket deviceSocket = args as Socket)
        {
            try
            {

                //lock the thread while we are creating the client IO Interface Manager
                lock (threadLock)
                {
                    byte[] readBuffer = new byte[1024];
                    // Read from buffer
                    int count = deviceSocket.Receive(readBuffer, 0, readBuffer.Length, SocketFlags.None);
                    String macAddress = "";//mac address sent by the device:
                    if (count > 0)
                    {
                        Encoding encoder = Encoding.ASCII;
                        int size = 0;
                        while (count > 0)
                        {
                            size += count;
                            // get string
                            macAddress += encoder.GetString(readBuffer, 0, count).Trim();
                            // Read from buffer
                            count = 0;
                        }
                        Console.WriteLine(string.Format("{0} trying to connect....", macAddress));
                    }
                    deviceSocket.Close();
                    readBuffer = null;
                }
                //threadLock = null;

            }
            catch (Exception ex)
            {
                Console.WriteLine("exception : " + ex.Message);
            }
        }
        args = null;
    }

  public  void Start()
    {
        StartDeviceListener();
    }
}`

【问题讨论】:

  • @Dimitry :如果您必须手动开始垃圾收集,那么您正在做一些非常糟糕或非常奇怪的事情。自己调用垃圾收集器是个好主意。
  • 尝试做 tousends 连接
  • 所以添加了 100kb,这是内存泄漏?
  • @rahul - 这看起来不像是一个真正的问题。仅在需要时或 GC 感觉需要时才会收集内存。要知道它是否是真正的内存泄漏,您需要一个内存分析器,因为它会在开始和结束时与应用程序挂钩,并且可以告诉您何时发生真正的内存泄漏。在分析时使用 GC.Collect() 非常好,因为您这样做只是为了查看等待收集的内存。您不会在生产应用程序中执行此操作。此外,虚拟内存是什么并不重要,这不是真正分配的内存号。
  • 您是否尝试过不创建自己的线程并使用 ThreadPool(好一点)甚至 Tasks(好很多,但取决于您使用的 .Net 版本)来完成这项工作?

标签: c# multithreading sockets memory memory-leaks


【解决方案1】:

但问题是内存不断增加并且永远不会释放。

这与内存泄漏相去甚远。您可能正在寻找一个不存在的问题。

在最后一个镜头中,您仍然有一个 10MB 的工作集,这实际上是零。
当您真的想查找/解决内存问题时,请使用分析器。

【讨论】:

  • 只有 1 个设备连接看起来不错;但如果我有 4K -5K 设备尝试连接,问题就会被放大。
  • 放大了多少,它是否趋于平稳或是否出现 OOM 异常?
  • 如果我让服务器运行一天,它会不断增加到 1 GB;之后我无法连接到任何设备。所以我有一个计划任务,每天重新启动一次 m/c 和服务器
  • 但我猜这是另一个版本(更多代码)而不是这里发布的内容。我看到一个单线程服务器,但没有明显的泄漏。问题可能出在其他代码中...
猜你喜欢
  • 1970-01-01
  • 2012-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多