C++ udp recvfrom减少下降

问题描述:

我有我的udp接收器插座相当标准的设置。我的发送者以36Hz发送数据,接收器以72Hz读取。每次发送12072个字节。C++ udp recvfrom减少下降

当我做猫/ proc/net/udp。我通常会得到

sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops 
7017: 0101007F:0035 00000000:0000 07 00000000:00000000 00:00000000 00000000  0  0 10636 2 0000000000000000 0   
7032: 00000000:0044 00000000:0000 07 00000000:00000000 00:00000000 00000000  0  0 14671 2 0000000000000000 0   
7595: 00000000:0277 00000000:0000 07 00000000:00000000 00:00000000 00000000  0  0 11113 2 0000000000000000 0   
7660: 00000000:22B8 00000000:0000 07 00000000:00004100 00:00000000 00000000 1000  0 251331 3 0000000000000000 352743 

你可以看到rx_queue在那里有一些值,读取速度不够快?

我的代码

int recv_len = recvfrom(s, buf, BUFLEN, MSG_TRUNC, (struct sockaddr *) &si_other, &slen); 
    // dont worry buflen is like 64000 no error here 

    std::cout <<" recv_len "<<recv_len<<std::endl; 

我总是得到输出recv_len 12072即使队列是相当大的?为什么是这样 ?有没有办法加快我的阅读或阅读队列中的所有消息?即使我的阅读频率较高,我也不明白什么是错误的。

+0

也许您的代码没有按照您的想法做它在做什么? (例如,你认为你的阅读是在72HZ,但你没有,或者有一个简单的bug,你没有发现......等等) – nos

UDP数据报总是作为一个完整的原子单元传播。如果您发送12072个UDP数据报,您的接收器将完全收到一个12072数据报或根本没有任何数据报 - 您将永远不会收到部分消息(*)或多个消息连接在一起。

请注意,使用此大小的数据报时,它们几乎肯定在IP层被分割,因为它们可能大于网络的MTU(最大传输单元)。在这种情况下,如果沿途或接收主机丢弃任何一个分段或发现其中一个分段被损坏,则整个UDP数据报将被丢弃。

(*消息可以被截断如果提供给recvfrom缓冲区太小,但它永远不会甚至被认为是用于接收如果整个邮件无法在内核中进行重组。)

如果你无法收到所有正在发送的消息,我会检查你是否需要增加分配给UDP的内核缓冲区空间。这是通过sysctl实用程序完成的。具体而言,您应该检查并可能调整net.core.rmem_maxnet.ipv4.udp_mem的值。请参见相应的文档:
https://www.kernel.org/doc/Documentation/sysctl/net.txt
https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt

最后,似乎有点好奇地谈论“读频率” - 我认为这意味着你是轮询插座每秒72次?为什么不专用一个线程来读取插座。然后该线程可以阻塞recvfrom,并且接收将以尽可能最小的延迟完成。 (在任何情况下,这都值得一试,即使仅用于测试 - 查看投票是否导致您无法跟上发件人。)

+0

是的,我也认为在内核级别上发生了一些事情。专用1线程可以减少掉落数量,但不会显着。但更重要的是它也减少了从发件人到我处理邮件的时间的延迟。我想我会研究udp_mem的大小,并与这些值一起玩。 – itsnevertoobadtoaskforhelp