【发布时间】:2014-03-07 01:27:33
【问题描述】:
我编写了一个简单的 UDP 服务器程序来了解更多可能的网络瓶颈。
UDP Server:创建一个UDP socket,将其绑定到指定的port和addr,并将socket文件描述符添加到epoll兴趣列表中。然后它的 epoll 等待传入的数据包。在接收到传入的数据包(EPOLLIN)时,它会读取数据包并仅打印接收到的数据包长度。很简单,对吧:)
UDP Client:我使用了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”命令在硬件级别没有太大损失,而在 appln 级别我看到如上所述的 53% 的损失。
因此,为了减少丢包,我尝试了以下方法:
- 使用renice 命令增加了我的示例程序的优先级。
- 增加接收缓冲区大小(在系统级别和进程级别)
将优先级提高到 -20:
雷尼斯 -20 2022
2022(进程 ID)旧优先级 0,新优先级 -20
将接收缓冲区大小提高到 16MB:
在过程级别:
int sockbufsize = 16777216;
setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,(char *)&sockbufsize, (int)sizeof(sockbufsize))
在内核级别:
cat /proc/sys/net/core/rmem_default
16777216
猫 /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。
感谢您的帮助和时间!!!
【问题讨论】:
-
我知道这是一个古老的问题,但您发现这个问题的核心是什么吗?我正在尝试重现 InErrors > RcvbufErrors 条件。
标签: renice linux linux-kernel udp epoll