recv()跳过UDP数据包

recv()跳过UDP数据包,c,linux,udp,recv,C,Linux,Udp,Recv,我编写了一个简单的程序来处理传入的UDP数据包。我向发送60000个UDP数据包,而此程序正在丢失数据包。带宽约为60-70 Mbit/s。 如果我并行调用tcpdump,那么我会看到内核接收到所有包。我还尝试了recvmsg和recvmmsg,得到了相同的结果 程序源代码: #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 信号原子退出条件=0; int袜子; 无效信号处理器(内部信号) { 出口条件=1; 停机(sock、SHUT\RDWR); 关闭(袜子); } 字符buff

我编写了一个简单的程序来处理传入的UDP数据包。我向发送60000个UDP数据包,而此程序正在丢失数据包。带宽约为60-70 Mbit/s。 如果我并行调用tcpdump,那么我会看到内核接收到所有包。我还尝试了recvmsg和recvmmsg,得到了相同的结果

程序源代码:

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
信号原子退出条件=0;
int袜子;
无效信号处理器(内部信号)
{
出口条件=1;
停机(sock、SHUT\RDWR);
关闭(袜子);
}
字符buff[10240];
int main(int argc,字符**argv)
{
内伦;
无符号长-长整体;
sock=插座(AF_INET,sock DGRAM,0);
信号(SIGTERM,信号处理器);
信号(SIGINT,信号处理器);
如果(sock==-1)
{
printf(“套接字中的错误()\n”);
返回-1;
}
rcv_addr中的结构sockaddr_;
memset(&rcv_addr,0,sizeof(rcv_addr));
rcv\u addr.sin\u family=AF\u INET;
rcv_addr.sin_addr.s_addr=INADDR_ANY;
rcv_addr.sin_port=htons(1024);
if(bind(sock,(const struct sockaddr*)和rcv_addr,sizeof(rcv_addr))<0)
{ 
printf(“绑定中出错()\n”);
返回-1;
}
当(!退出条件)
{
len=recv(sock,(char*)buff,10240,
MSG_WAITALL);
如果(len>0)
{
总体++;
}
}
printf(“总体:%lld\n”,总体);
}

问题解决了。我对tcpdump的看法是错误的,不是所有的数据包都传递到内核。我也没有详细描述这个问题。程序运行在单核ARM处理器上,UDP数据包的有效负载是256字节,所以CPU跟上数据流,结果内核UDP队列流出,我看到数据包丢失。iperf3有1448字节的有效负载,工作正常。如果我将iperf3有效负载包减少到256字节,它也会开始丢弃数据包。
为了解决这个问题,我将有效负载增加到512字节,增加了net.core.rmem_max、net.core.rmem_default和NIC环形缓冲区,所有这些都可以正常工作。

Well UDP是不可靠的。您甚至可以在接口和程序之间的途中丢弃数据包。发生这种情况的一个原因是您的程序的速度不够快,无法处理所有传入的数据包。我不认为我曾经在UDP上使用过recv:只在TCP上使用过。另一个建议是:检查
if(len>0)
,这是正确的(至少您执行了一些检查),但您没有发现
lenI不是说这是系统性能问题,而是程序中的性能问题。您的程序是否足够快,可以处理所有收到的包?您显示的代码是否与实际运行的代码相同?它是一个完全复制问题的变量吗?顺便问一下,变量的初始值是多少?请记住,未初始化的局部变量实际上是未初始化的,并且会有一个不确定的(看起来是随机的或垃圾的)值。也许如果你初始化它,你会得到更好的结果?