我写了一个简单的 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%。
因此,为了减少丢包,我尝试了这些:
- 使用 renice 提高了我的示例程序的优先级命令。
- 增加接收缓冲区大小(在系统级别和进程级别)
将优先级提高到 -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%。
数据包丢失显着减少。但我有以下问题:
- 能否进一步减少丢包?!?我知道我在这里很贪心 :) 但我只是想看看是否有可能进一步减少数据包丢失。
- 与 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/