套接字服务器使用了太多资源

时间:2012-04-30 10:42:21

标签: c# sockets

我正在创建一个基于套接字的遥测应用程序,我使用两个无线调制解调器发送/接收数据,一个应用程序通过调制解调器1发送数据,另一个程序通过调制解调器2获取数​​据,我的发送间隔是一秒,它似乎接收器应用程序(服务器)正在使用大部分CPU和RAM资源(99%的CPU使用率!),其内存使用量稳步增长!所以几分钟后我的程序几乎停止响应并且我的数据根本不正确,所以数据无法解析,似乎我的程序收到了几个已发送数据的副本,我的原始数据包大约是70个字节,但是经过一些它的大小增加秒,我认为我的接收缓冲区已满,数据与之前的数据混合,我正在寻找一些建议,这是我在服务器程序中的接收处理程序:

private void DataReceive()
    {
        handler.ReceiveBufferSize = 100;

        try
        {
            byte[] bytes = new byte[100];
            int byteRec;
            while (true)
            {
                timer1.Enabled = true;
                while (true)
                {
                    byteRec = handler.Receive(bytes);
                    if (byteRec > 0)
                    {
                        data = System.Text.Encoding.UTF8.GetString(bytes, 0, byteRec);
                        break;
                    }
                }

                if (data.Length >= 30)
                {
                    if (data.Substring(0, 1) == "#")//pasrse data, correct!
                    {
                        label27.Text = data.Length.ToString();
                        textBox1.Text = data;
                        string a = data.Substring(1);

                        string[] b = a.Split('-');

                        SetControlPropertyThreadSafe(lblTotal, "Text", b[0]);
                        SetControlPropertyThreadSafe(lblFlow, "Text", b[1]);

                        float real_analog2 = (1 - (((20 - float.Parse(b[4])) / (20 - 4)))) * Analog2_Max;
                        if (real_analog2 < 0)
                            real_analog2 = 0;
                        SetControlPropertyThreadSafe(lblAnalog, "Text", real_analog2.ToString());

                        if (b[2] == "1")//off
                            SetControlPropertyThreadSafe(lblMotion, "Text", "off");
                        else if (b[2] == "0")//on
                            SetControlPropertyThreadSafe(lblMotion, "Text", "on");

                        if (b[3] == "1")//off
                            SetControlPropertyThreadSafe(lblMotion2, "Text", "off");
                        else if (b[3] == "0")//on
                            SetControlPropertyThreadSafe(lblMotion2, "Text", "on");

                        SetControlPropertyThreadSafe(lblV1, "Text", b[5]);
                        SetControlPropertyThreadSafe(lblV2, "Text", b[6]);
                        SetControlPropertyThreadSafe(lblV3, "Text", b[7]);
                        SetControlPropertyThreadSafe(lblI1, "Text", b[8]);
                        SetControlPropertyThreadSafe(lblI2, "Text", b[9]);
                        SetControlPropertyThreadSafe(lblI3, "Text", b[10]);
                        SetControlPropertyThreadSafe(lblLevelPercent, "Text", b[11]);
                        SetControlPropertyThreadSafe(lblLevelValue, "Text", b[12]);
                    }
                }
                FillLstMsg(data);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

2 个答案:

答案 0 :(得分:2)

当你做一段时间(true)时,你应该总是在那里添加Thread.Sleep(x)。这会阻止循环变成紧凑的循环并占用你的CPU。

你只需要睡几毫秒,这就足够了。

至于内存消耗,我怀疑你可能在某处泄漏。还要考虑当CPU非常繁忙时,.NET框架将推迟垃圾收集,直到它不会对系统产生影响(即CPU使用率较低),或者系统内存不足。

当您添加Thread.Sleep时,可能会发生垃圾收集,并且内存使用率将保持稳定。

答案 1 :(得分:2)

基本上我认为你的做法是错误的。

您如何说收到的数据大小? 第一个数据包消息何时结束,另一个数据包消息何时开始? 你知道你的完整数据包消息有多大吗?

在接收来自另一端的数据包时,您应该仔细验证这些问题。

我在TCP实现上继承的一个常见做法是首先发送即将发送的数据包大小,然后根据该数据包大小处理该消息。这将为您提供出色的灵活性,从而创建更强大的TCP实施。如果你这样做,你可以随意发送任意数量的数据包而不会崩溃。

我也看到你搞砸了演示代码和接收数据代码。 您应该创建一个单独的类库来处理所有TCP通信操作, 并将收到的数据扔到消费者应用程序中。

Nito Async库对我来说是一个非常好的起点。你可以看到他在做什么,虽然它是太先进的技术和真正优秀的代码,你可以抓住基本的想法。

从他博客中的这个漂亮的解释开始,然后在codeplex中捕获代码。我现在看到他更新了一些东西,所以你可以把所有的努力都花在你的代码上,如果它适合你的话,甚至是他的代码:)

http://nitoprograms.blogspot.com/2009/04/tcpip-net-sockets-faq.html

快乐阅读!