UDP通信中,能实时接收50ms/帧(1000字节)的数据吗?我现在的情况是:
有三个采集装置同时(时间同步误差在5ms内)向一个计算机发送数据,发送速度都是50ms/帧(1000字节),
我的数据接收程序如下:
一个线程专门收数,根据接收到的数据不同的发送端口,放入不同的缓冲区
另一个线程专门处理缓冲区中的数据。碰到的问题是:
按如下程序接收数据时,每次接收完3帧数据时间间隔比较长,短的约十几毫秒,长的约100多毫秒。
这样造成我前一拨的3帧数据只收到2帧,后一拨的数据又来了,使得接收混乱。
(我不能等待收完几帧数据后通过分帧处理,只有50ms内处理完数据才是有意义的)请问高人:我该如何处理才能加快我的接收速度。谢谢大家帮忙!
//接收数据线程
UINT CUDPMonitorDlg::ListenThread(LPVOID pParam)
{
CUDPMonitorDlg *pDlg=(CUDPMonitorDlg *)pParam;
while (1)
{
int nRecvCounts = recvfrom(pDlg->socket1,(char *)cRecvBuff,1024,0,(struct sockaddr*)&(pDlg->from),&fromlen);
if (nRecvCounts > 0)
{
//通过不同的端口判断不同的采集装置
if (ntohs(pDlg->from.sin_port) == 9000)
{
memcpy(&pApp->m_chSDBuff[0], cRecvBuff, nRecvCounts);
TRACE("Received datagram from %s ,端口:%d,  长度:%d\n",chRecvIp, ntohs(pDlg->from.sin_port), nRecvCounts);
}
if (ntohs(pDlg->from.sin_port) == 9001)
{
memcpy(&pApp->m_chSDBuff[1], cRecvBuff, nRecvCounts);
TRACE("Received datagram from %s ,端口:%d,  长度:%d\n",chRecvIp, ntohs(pDlg->from.sin_port), nRecvCounts);
}
if (ntohs(pDlg->from.sin_port) == 9002)
{
memcpy(&pApp->m_chSDBuff[1], cRecvBuff, nRecvCounts);
TRACE("Received datagram from %s ,端口:%d,  长度:%d\n",chRecvIp, ntohs(pDlg->from.sin_port), nRecvCounts);
}
//打印接收到数据时的时间(精确到毫秒)。
//...
}
// Sleep(1);   加不加延时效果都不好
}
return 0;
} //处理数据线程
在另一个线程中处理pApp->m_chSDBuff中的数据。请问高人:我该如何处理才能加快我的接收速度。谢谢大家帮忙!

解决方案 »

  1.   

    我希望是UDP,谢谢我的程序的问题出在哪里?
      

  2.   

    我只是会TCP的iocp,UDP的iocp不太了解,请指点
      

  3.   

    现有处理足够了,3个采集端总共只需要60KB(3*1KB*1000/50)的带宽,对于局域网来说小菜一碟。
    UDP包使用1K大小也完全满足要求。
    使用缓冲机制也完全没问题。问题在于你的处理线程要足够快(这个可以自己测试),否则再大的缓冲区也不够用。
      

  4.   

    我只是会TCP的iocp,UDP的iocp不太了解,请指点
    ======================
    两个是一样的,不断投递特定数量的WSARecvFrom就好了。
      

  5.   

    碰到WSASendTo的完成包,给一个通知(比如传输文件时的进度)就直接丢弃。
      

  6.   

    我也觉得是jameshooo说的是,50ms足够接收1000字节的数据了
    主要是在接收线程中不要花太多的时间在“接收”这个任务以外的任务
    楼主可以查看下你的时间都耗费在哪里,我想瓶颈不会在recvfrom上
      

  7.   

    局域网50ms肯定没问题。先帮你小优化一下:int   nRecvCounts
    u_short  uPort
    struct sockaddr* psaFrom = (struct   sockaddr*)&(pDlg-> from);
    SOCKET sRecv = pDlg-> socket1;while   (1) 

    nRecvCounts   =   recvfrom(sRecv,(char   *)cRecvBuff,1024,0,psaFrom,&fromlen); 
    if   (nRecvCounts   >   0) 

    uPort = ntohs(psaFrom->sin_port);
    //通过不同的端口判断不同的采集装置 switch( uPort  )
    {
       case : 
        ..............
    }
    你的 while 重复计算太多啦。TRACE("Received   datagram   from   %s   ,端口:%d,     长度:%d\n",chRecvIp,   ntohs(pDlg-> from.sin_port),   nRecvCounts); 如果是在 debug 模式, 上面的,也会占用不少的cpu.
      

  8.   

    楼上的怎么就优化了一个switch啊,这个楼主只要把后面if的else if就跟你一样了其实到底50m处理1000字节够不够,只要把recvfrom以外的工作注释掉测试就okay了
    如果再不行,看看是不是别的线程占用CPU时间太多了现在我在搞的项目就每个客户端3秒发3000字节,同时要处理8个客户端
    接收到后要解压缩数据,再计算,再保存到本地,再每4ms取4字节画波形图
    8个客户端同时进行,中间还会另外收到控制信息,需要同时显示CPU占用率还不到50%,而且知道还有许多可以优化的地方,但是也懒得去改了
      

  9.   

    楼上的怎么就优化了一个switch啊,这个楼主只要把后面if的else   if就跟你一样了 
    你仔细看过啦?switch的原因,是不象写一堆 if else。黑体部分才是优化。
      

  10.   


    我将接收线程改为只是显示接收到数据的时间,但从打印的时间来看,3帧数据还是间隔好几十毫秒,完全不能满足要求!
    请大家指点,我的问题到底在哪里,谢谢!UINT CUDPMonitorDlg::ListenThread(LPVOID pParam)
    {
    CUDPMonitorDlg *pDlg=(CUDPMonitorDlg *)pParam;
    while (1)
    {
    int nRecvCounts = recvfrom(pDlg->socket1,(char *)cRecvBuff,1024,0,(struct sockaddr*)&(pDlg->from),&fromlen);
    if (nRecvCounts > 0)
    {
    //打印接收到数据时的时间(精确到毫秒)。
    ::GetNowTime()
    }
    }
    return 0;
    }
    void GetNowTime()
    {
    CString m_strTime;
    struct _timeb timebuffer;
    char *timeline;
    //获得毫秒级的时间
    _ftime( &timebuffer );
    timeline = ctime(&(timebuffer.time));
    //格式化时间
    m_strTime.Format("%.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20]);
    TRACE(m_strTime);
    }
      

  11.   

    有三个采集装置同时(时间同步误差在5ms内)向一个计算机发送数据楼主查问题先从源头查起吧,发送端是不是正确发送,如果正确发送,那应该是每50ms内有3帧数据,虽然发送端时间同步误差在5ms内,但是网络延时后,接收不一定先查发送端是否正确发送
    再查丢包情况
    再查延时情况
    最后综合什么的情况,判断程序是否运行正确,还是有设计上的问题,性能没能达到要求
      

  12.   

    非常感谢大家的关注和帮助!我在收数的机器上安装了ethereal,通过抓包可以看到各个数据包到达的时间,的确在5ms内。也就是说采集的数据的确准时到达我的网口了。我怎么也搞不明白,到底哪个地方延时了!?
      

  13.   

    你就写个console程序
    收到就把时间显示出来,数据直接丢弃
    如果还是不行,那就见鬼了int main(...)
    {
       SOCKET s;
       sockaddr_in addrClient;
       char buff[1024];   s=socket(...);
        ...      //绑定,监听,接收,建立连接
       while(0<recv(...))
       {
         ...       //显示时间
       }
       return 0;
    }
      

  14.   

    包过大肯定会有影响的,最好采取割包粘包的方式,try RTcP
      

  15.   

    但是如果你是要在100ms下接收500个1K大小的UDP包,在100M以太网环境却是没问题的