标题:关于在一个线程中处理多个UDP通道通信数据引起CPU和内存占用高,程序运行不 ...
只看楼主
鸿蒙之灵
Rank: 4
来 自:异次元裂缝
等 级:贵宾
威 望:11
帖 子:126
专家分:244
注 册:2016-8-22
结帖率:66.67%
已结贴  问题点数:20 回复次数:6 
关于在一个线程中处理多个UDP通道通信数据引起CPU和内存占用高,程序运行不流畅
问题提出:
我的软件要和多个软件进行通信,假如有n个软件和我的软件通信,我就建立n个UDP通道,这些UDP通道收来的数据我要在一个线程里面全部处理,现在该部分已经实现,但是出现CPU占用高(50%左右),内存占用高(240M左右),如何能够在不动该接收机制的前提下优化该部分

数据接收线程如下:
首先我是绑定套接字
程序代码:
    ip_Flag = FALSE;  //初始化标志量为假,此处若初始化为真,无IP通道时会启动线程
    for (unsigned int i = 0; i < ComNum; i++)
    {
        if (FALSE == Init_IP(i))   //Init_IP(i)绑定套接字成功返回真,否则为假
        {
            ip_Flag = FALSE;
            break;      //此处有一个通道未创建成功,则跳出循环,且不允许启动接收数据线程
        }
        else
        {
            ip_Flag = TRUE;
        }
    }
    if (TRUE == ip_Flag)
    {
        /*启动接收数据线程*/
        AfxBeginThread(ReceiveUDP, this, THREAD_PRIORITY_NORMAL, 0, 0, NULL);   //该线程不启动时,程序CPU占用连10%都不会超过,基本常态就在1%左右。
    }


接收数据线程如下:
程序代码:
UINT CMonitorView::ReceiveUDP(LPVOID p)
{
    int retval;
    int i;
    char RecvArray[1024]={0}; //接收数据存储缓冲区
    unsigned char RecvArray1[1024]={0};//格式转换后数据存储缓冲区
    unsigned char RecvArray2[1024]={0};//校验后数据存储缓冲区
    BOOL m_recflag=FALSE;
    CMonitorDoc *pDoc;
    CMonitorView *pView;

    CMainFrame *pFrame = (CMainFrame *)(AfxGetApp()->m_pMainWnd);
    pView = (CMonitorView *)(pFrame->GetActiveView());
    pDoc=(CMonitorDoc *)(pFrame->GetActiveDocument());
    int len=sizeof(SOCKADDR);

    unsigned int Framelen=0;
    SOCKADDR_IN addr[10];
    SOCKET sock[10];
    if (0 == pView->ComNum) //简单防护
    {
        return 0;
    }
    else
    {
        for (int a = 0; a < pView->ComNum; a++)
        {
            if (10 <= a)
            {
                break;
            }
            addr[a] = pView->ComArray[a].addrSrv;    //ComArray数组存放着各UDP通道相关值
            sock[a] = pView->ComArray[a].sockSrv;
        }
    }

    for(;;)
    {
        for (unsigned int m = 0; m < pView->ComNum; m++)
        {
            memset(RecvArray,0,1024);
            memset(RecvArray1,0,1024);
            memset(RecvArray2,0,1024);
            //接收数据
            retval=recvfrom(sock[m],RecvArray,1024,0,(SOCKADDR*)&(addr[m]),&len);
            memcpy(RecvArray1,RecvArray,1024);

            //通信数据格式校验
            for(i=0;i<=1023;i++)
            {
                if(/*帧头校验通过*/)
                {
                    Framelen = /*通过数据协议取出对应数据计算通信数据包长度*/;
                    if(1024 <= i+Framelen )
                    {
                         break;   //简单防护
                    }
                    if(/*帧尾校验通过*/)
                    {
                        memcpy(RecvArray2,RecvArray1+i,Framelen);
                        m_recflag=TRUE;
                        break;
                    }
                }
            } 
            if(m_recflag==TRUE)
            {
                m_recflag=FALSE;
                /*此处解析接收到的数据协议*/
            }
        }
    }
    for (unsigned int m = 0; m < pView->StationComNum; m++)
    {
        closesocket(pView->StationComArray[m].sockSrv);
        WSACleanup();
    }
}


[此贴子已经被作者于2020-9-9 09:44编辑过]

搜索更多相关主题的帖子: 通信 int 线程 接收 数据 线程 接收 int 通信 数据 
2020-09-09 09:23
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:507
帖 子:8890
专家分:53117
注 册:2011-1-18
得分:10 
for(;;) 是死循环吧?!加个 Sleep(1) 试试。
2020-09-09 10:16
鸿蒙之灵
Rank: 4
来 自:异次元裂缝
等 级:贵宾
威 望:11
帖 子:126
专家分:244
注 册:2016-8-22
得分:0 
回复 2楼 rjsp
按照你说的,加了这个确实是好了,但是我有一个不确定的点,希望你帮我确定一下:

sleep(1);按照计算机时间精度,应该是休眠该线程10毫秒左右吧,和我程序通信的软件最小发送周期为100毫秒,我觉得不会出现丢失数据的情况,但我不是很确定,我的程序运行周期为500ms;

期待您的答复!谢谢

对待编程,要像对待情人一样
2020-09-09 10:32
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:507
帖 子:8890
专家分:53117
注 册:2011-1-18
得分:0 
你的for(;;)会发生空耗的情况,这时候线程一直在运行,所以CPU占用率就高了。
Sleep(0)的话,当没有其它线程需要运行时,此线程并不暂停;所以用Sleep(1)缩减空耗CPU的时间。

当然,Sleep(1)也不是正道,正道应该消除一切空耗的情况。
此外,多个线程同时访问 pView->ComNum 也是不安全的;
memset 等都没必要,应该根据 len 只处理读取到的信息;
……
2020-09-09 10:52
纯蓝之刃
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:76
帖 子:554
专家分:3690
注 册:2019-7-29
得分:10 
retval=recvfrom(sock[m],RecvArray,1024,0,(SOCKADDR*)&(addr[m]),&len);
if(retval<=0)
continue;

可以加一个判断是否接收到数据包的操作。这样可以减少无效数据的读取,间接缩短了每个连接读取两封报文之间的时间间隔。

一沙一世界,一花一天堂。无限掌中置,刹那成永恒。
2020-09-09 11:01
鸿蒙之灵
Rank: 4
来 自:异次元裂缝
等 级:贵宾
威 望:11
帖 子:126
专家分:244
注 册:2016-8-22
得分:0 
回复 4楼 rjsp
程序之前一直用的就是UDP通信,并且这种一个线程访问一个UDP通道时候是没有这个问题的,为什么访问多个的时候就会占用这么高,一个线程访问一个UDP通道时候也没有sleep,同样使用for(;;),是没有问题的,所以你说的空耗这个应该不是特别严重,memset这个也占不了那么多资源,感觉是这个线程一直在占用CPU资源,其他线程得不到有效执行,导致的,但一个线程访问一个通道,这样就不会出现该问题,现在测试过后发现会偶发性的丢失数据,有没有什么办法能让线程在不丢失数据的情况下实现和其他线程合理使用CPU资源呢

[此贴子已经被作者于2020-9-9 12:48编辑过]


对待编程,要像对待情人一样
2020-09-09 12:40
鸿蒙之灵
Rank: 4
来 自:异次元裂缝
等 级:贵宾
威 望:11
帖 子:126
专家分:244
注 册:2016-8-22
得分:0 
回复 5楼 纯蓝之刃
这个能节省出来的量不是很多,效果不明显,主要我疑惑的是为什么一个线程访问一个通道时候,用这种方式他不会占用那么高,而访问多个的时候,不用sleep就会占用这么高,有没有什么办法能让线程及时让出资源的同时,又确保通道来的数据都能被解析到

对待编程,要像对待情人一样
2020-09-09 12:46



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-503106-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.227357 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved