linux - UDP 数据包丢弃 - INErrors 与 .RcvbufErrors

标签 linux linux-kernel udp epoll

我写了一个简单的 UDP 服务器程序来了解更多可能的网络瓶颈。

UDP Server:创建一个UDP套接字,将其绑定(bind)到指定的端口和地址,并将套接字文件描述符添加到epoll兴趣列表。然后它的 epoll 等待传入的数据包。在接收到传入数据包(EPOLLIN)时,它会读取数据包并仅打印接收到的数据包长度。很简单,对吧:)

UDP客户端:我使用hping如下图:

hping3 192.168.1.2 --udp -p 9996 --flood -d 100

当我以每秒 100 个数据包的速度发送 udp 数据包时,我没有发现任何 UDP 数据包丢失。但是当我淹没 udp 数据包时(如上面的命令所示),我发现有大量数据包丢失。

测试 1: 当 26356 个数据包从 UDP 客户端泛洪时,我的示例程序仅收到 12127 个数据包,其余 14230 个数据包被内核丢弃,如/proc/net/snmp 输出所示。

cat /proc/net/snmp | grep Udp:
Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors
Udp: 12372 0 14230 218 14230 0

对于 Test1 丢包率约为 53%。

我在客户端和服务器端使用“ethtool -S ethX”命令验证了硬件级别没有太大损失,而在应用程序级别,我看到如上所述损失了 53%。

因此,为了减少丢包,我尝试了这些:
- 使用 提高了我的示例程序的优先级命令。
- 增加接收缓冲区大小(在系统级别和进程级别)

将优先级提高到 -20:

renice -20 2022
2022 (process ID) old priority 0, new priority -20

将接收缓冲区大小增加到 16MB:

At Process Level:
int sockbufsize = 16777216;
setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,(char *)&sockbufsize, (int)sizeof(sockbufsize))
At Kernel Level:
cat /proc/sys/net/core/rmem_default
16777216
cat /proc/sys/net/core/rmem_max
16777216

进行这些更改后,执行 Test2。

测试 2: 当 1985076 个数据包从 UDP 客户端泛洪时,我的示例程序接收到 1848791 个数据包,剩余的 136286 个数据包被内核丢弃,如/proc/net/snmp 输出所示。

cat /proc/net/snmp | grep Udp:
Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors
Udp: 1849064 0 136286 236 0 0

对于 Test2 丢包率是 6%。

数据包丢失显着减少。但我有以下问题:

  1. 能否进一步减少丢包?!?我知道我在这里很贪心 :) 但我只是想看看是否有可能进一步减少数据包丢失。
  2. 与 Test1 不同,在 Test2 中,InErrors 与 RcvbufErrors 不匹配,并且 RcvbufErrors 始终为零。有人可以解释一下背后的原因吗?!? InErrors 和 RcvbufErrors 之间到底有什么区别。我了解 RcvbufErrors 但不了解 InErrors。

感谢您的帮助和时间!!!

最佳答案

调整 Linux 内核的网络堆栈以减少数据包丢失有点复杂,因为从驱动程序一直到网络堆栈都有很多调整选项。

我写了一个long blog post从上到下解释所有调整参数并解释 /proc/net/snmp 中每个字段的含义,这样您就可以弄清楚为什么会发生这些错误。看一下,我认为它应该可以帮助您将网络掉线率降至 0。

关于linux - UDP 数据包丢弃 - INErrors 与 .RcvbufErrors,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21664950/

相关文章:

c++ - 在 C++ 中查看 UDP 消息

javascript - FFMPEG UDP 输出不起作用

c++ - 使用 sin() 生成的声音中的金属声音

c - openssl 握手失败

linux - 如何获取内核设备驱动程序代码中各个点的堆栈跟踪

linux - 当 linux 系统调用被阻塞时如何以及何时设置 -EINTR

c++ - 处理 tcp/udp 接收的最佳方式。

python - linux上的两个python版本。如何将 2.7 设为默认值

linux - 分析系统调用

c - 在 Linux 内核模块(驱动程序)临界区等待用户空间输入