首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#中的TCP服务器在2-3天后造成100%的CPU使用率。

C#中的TCP服务器在2-3天后造成100%的CPU使用率。
EN

Stack Overflow用户
提问于 2013-06-04 08:21:57
回答 2查看 1.9K关注 0票数 2

下面是我为一个非常简单的TCP (基本上是异步服务器套接字示例- http://goo.gl/Ix5C -稍微修改)编写的代码:

代码语言:javascript
复制
    public static void InitiateListener()
    {
        try
        {
            allDone = new ManualResetEvent(false);
            configFile = new XmlConfig();                
            StartListening();
        }
        catch (Exception exc)
        {
            LogsWriter f = new LogsWriter(configFile.ErrorLogsPath);
            f.WriteToFile(exc.Message);
            f.CloseFile();
        }

    }

    private static void StartListening()
    {      
        try
        {
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, configFile.Port);
            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            listener.Bind(localEndPoint);
            listener.Listen(100);                

            while (true)
            {
                // Set the event to nonsignaled state.
                allDone.Reset();                    

                // Start an asynchronous socket to listen for connections.
                listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);

                // Wait until a connection is made before continuing.
                allDone.WaitOne();
            }
        }
        catch (Exception exc)
        {
            throw exc;
        }
    }

    public static void AcceptCallback(IAsyncResult ar)
    {
        allDone.Set(); // Signal the main thread to continue.               

        // Get the socket that handles the client request.
        Socket listener = (Socket)ar.AsyncState;
        Socket handler = listener.EndAccept(ar);

        // Create the state object.
        StateObject state = new StateObject();
        state.workSocket = handler;

        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
    }

    public static void ReadCallback(IAsyncResult ar)
    {
        string hexData = string.Empty;

        // Retrieve the state object and the handler socket from the asynchronous state object.
        StateObject state = (StateObject)ar.AsyncState;
        Socket handler = state.workSocket;

        try
        {
            // Read data from the client socket. 
            int bytesRead = handler.EndReceive(ar);                

            if (bytesRead > 0)
            {
                hexData = BitConverter.ToString(state.buffer);

                if (hexData.Contains("FA-F8")) //heartbeat - echo the data back to the client.
                {
                    byte[] byteData = state.buffer.Take(bytesRead).ToArray();
                    handler.Send(byteData);
                }
                else if (hexData.Contains("0D-0A")) //message
                {
                    state.AsciiData = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
                    state.ParseMessage(configFile);
                }
            }
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);                
        }
        catch (Exception)
        {
            handler.Shutdown(SocketShutdown.Both);
            handler.Close();
        }
    }

这都是在Windows服务中完成的。并且CPU在大约2天半的运行后达到100%,完全可以接受。这种情况现在已经发生了三次-- windows服务总是工作正常,功能正常,几乎没有CPU资源,但是在第三天的某个时候,它会达到100%,并停留在那里直到服务被重新分配。

我得到了非常简单的CSV数据包,我用这种方法快速地解析并通过webservice将其发送到数据库: state.ParseMessage(configFile);即使当CPU是100%时,数据库也会得到相当可靠的填充。但我知道这可能是我需要调查的地方?

代码中的哪些其他区域看起来可能导致了问题?我刚开始异步编程,所以我不知道是否需要手动关闭线程。另外,这可能是另一个问题: handler.BeginReceive(state.buffer,0,StateObject.BufferSize,0,new AsyncCallback(ReadCallback),state);

在ReadCallback内部调用该行。我这样做是为了维护与客户端的连接并继续接收数据,但也许我应该关闭套接字并强制新连接?

你能给我一些建议吗?谢谢

EN

回答 2

Stack Overflow用户

发布于 2016-03-27 15:33:08

而不是启动方法中的循环while(true),我们需要调用

代码语言:javascript
复制
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);

从AcceptCallback方法一旦完成接受新客户端。

票数 0
EN

Stack Overflow用户

发布于 2016-03-27 16:27:29

您需要通过bytesRead == 0检测断开连接。现在你没有,而是发布另一个阅读。

看起来您已经复制了MSDN示例代码。我之所以能看出来,是因为异步IO和事件的组合是无孔不入的。当您使用同步IO时,所有这些代码都变得更简单。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16912955

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档