c++ - Linux UDP丢包的原因

标签 c++ c linux networking udp

我有一个接收有序 UDP 数据包的 Linux C++ 应用程序。由于排序,我可以很容易地确定数据包何时丢失或重新排序,即何时遇到“间隙”。系统有一个恢复机制来处理间隙,但是,最好首先避免间隙。使用一个简单的基于 libpcap 的数据包嗅探器,我确定硬件级别的数据没有间隙。但是,我在我的申请中看到了很多空白。这表明内核正在丢弃数据包;通过查看 /proc/net/snmp 文件可以确认。当我的应用程序遇到间隙时,Udp InErrors 计数器会增加。

在系统层面,我们增加了最大接收缓冲区:

# sysctl net.core.rmem_max
net.core.rmem_max = 33554432

在应用程序级别,我们增加了接收缓冲区大小:

int sockbufsize = 33554432
int ret = setsockopt(my_socket_fd, SOL_SOCKET, SO_RCVBUF,
        (char *)&sockbufsize,  (int)sizeof(sockbufsize));
// check return code
sockbufsize = 0;
ret = getsockopt(my_socket_fd, SOL_SOCKET, SO_RCVBUF, 
        (char*)&sockbufsize, &size);
// print sockbufsize

在调用 getsockopt() 之后,打印的值始终是设置值的 2 倍(上例中为 67108864),但我相信这是意料之中的。

我知道未能足够快地使用数据会导致数据包丢失。然而,这个应用程序所做的只是检查排序,然后将数据推送到队列中;实际处理在另一个线程中完成。此外,这台机器很现代(双 Xeon X5560,8 GB RAM)并且负载非常轻。我们实际上有几十个相同的应用程序以更高的速率接收数据,它们没有遇到这个问题。

除了消耗太慢的应用程序之外,还有其他原因会导致 Linux 内核丢弃 UDP 数据包吗?

FWIW,这是在 CentOS 4 上,内核为 2.6.9-89.0.25.ELlargesmp。

最佳答案

如果您的线程数多于内核数并且它们之间的线程优先级相同,则接收线程很可能需要时间来刷新传入缓冲区。考虑以比其他线程更高的优先级运行该线程。

同样,尽管通常效率较低,但将接收线程绑定(bind)到一个内核,这样您就不会承受在内核之间切换和相关缓存刷新的开销。

关于c++ - Linux UDP丢包的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5913298/

相关文章:

c++ - 保持对象存活的问题

c - 架构 x86_64 的 undefined symbol - C

c - 如何将真实文件夹添加到我的 Netbeans C 项目中?

c - 交换 char 数组的元素可以工作,但交换 char 字符串的元素会导致核心转储

c++ - 使用函数指针?

c++ - C++ 中的 sprintf?

linux - 通过 shell 脚本检查文件夹和内部文件是否存在

linux - Google Cloud Ops Agent Mongo 集成错误 - AuthenticationFailed : SCRAM authentication failed, 存储 key 不匹配

在Linux中编译C代码

c++ - 使用 Visual Studio 2013 进行过程 C++ 编程