在前兩篇文章里,我們探討了不少UDP丟包的解決方案。經過幾年的摸索測試,其實方法非常簡單, 無需修改代碼。
1. Windows 下設置UDP緩存
這個方法可以一勞永逸解決UDP的收發丟包問題,只要添加注冊表項目并重啟即可。即使用Qt的信號與槽,QUdpSocket用信號-槽在Debug模式下也一包不丟。把下文存儲為“udp.reg”,而后雙擊,即可修改注冊表。
Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters]
"DefaultReceiveWindow"=dword:00100000
"FastSendDatagramThreshold"=dword:00002800
"DefaultSendWindow"=dword:00100000
設置好后,即使在Debug模式下,也一包不丟:
qtcpp_demo/udp_loss_test/build/debug/udp_loss_test.exe
Start...
QUdpSocket LOOP:Send 10000, Recv 10000, Lost 0.
Start...
QUdpSocket Signal and Slots:Send 10000, Recv 10000, Lost 0.
Start...
Local Socket :Send 10000, Recv 10000, Lost 0.
Finished sending. Closing socket.
Exiting.
2. Linux 下設置UDP緩存
Linux 下,默認的緩存已經足夠了,Debug版本也不會丟包。如果需要,則設置緩存:
sudo sysctl -w net.core.rmem_default=100000
net.core.rmem_default = 100000
sudo sysctl -w net.core.rmem_max=1000000
net.core.rmem_max = 1000000
參考:
https://www.baeldung.com/linux/udp-socket-buffer
3. 代碼級別的設置
想要單獨用代碼設置1個套接字的緩存,則使用:
(參考:https://blog.csdn.net/test1280/article/details/79776938)
int rcvBufSize = 1024*1024*16;int optlen = sizeof(rcvBufSize);if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvBufSize, optlen) < 0){printf("setsockopt error=%d(%s)!!!\n", errno, strerror(errno));goto error;}printf("set udp socket(%d) recv buff size to %d OK!!!\n", sockfd, rcvBufSize);
4. 測試工程
測試工程參考:
https://gitcode.net/coloreaglestdio/qtcpp_demo/-/tree/master/udp_loss_test
5 效果
在上網本Intel? Celeron? CPU J1800 @ 2.41GHz 2.41 GHz下,Qt 6.8.0 MINGW64 Debug模式,
Starting C:\projects\qtcpp_demo\udp_loss_test\build\Desktop_Qt_6_8_0_shared_MinGW_w64_UCRT64_MSYS2-Debug\debug\udp_loss_test.exe...
Start...
QUdpSocket LOOP:Send 10000, Recv 10000, Lost 0.
Start...
QUdpSocket Signal and Slots:Send 10000, Recv 10000, Lost 0.
Start...
Local Socket :Send 10000, Recv 10000, Lost 0.
Finished sending. Closing socket.
Exiting.