UDP服务器:创建一个UDP套接字,将其绑定到指定的端口和地址,并将套接字文件描述符添加到epoll兴趣列表中。然后,它的epoll等待传入的数据包。在接收到传入的数据包(EPOLLIN)时,它会读取该数据包并打印接收到的数据包长度。非常简单,对吧 :)
UDP客户端:我使用如下所示的hping:
hping3 192.168.1.2 --udp -p 9996 --flood -d 100
当我每秒发送100个udp数据包时,我没有发现任何UDP数据包丢失。但是当我洪水般地发送udp数据包(如上述命令所示),我看到显着的数据包丢失。
测试1: 当从UDP客户端洪泛26356个数据包时,我的样本程序仅接收到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(进程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
cat /proc/sys/net/core/rmem_max
16777216
完成这些更改后,执行Test2。
Test2: 当从UDP客户端发送1985076个数据包时,我的样例程序接收了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。
感谢您的帮助和时间!!!