QUdp packets loss at reciver.
-
Hi all,
Im trying to use QUdpSocket to transmit some images from clinet to server,which are about 0.5~1.5MB.
And i found i cant pack the image data in one packet(it`s too big).
So i divide them into several pieces,each piece is about 4096 bytes.
The clinet shows that my image is divided into about 380+ pieces,but at my server,there is almost half packets loss.Struct UdpDatagramHead:
const int UdpDatagramMaxSize = 4096; ///Udp typedef struct { int nDataTotalSize; int nDatagramIndex; int nDatagramSize; int nOffset; int nIsColor; int nWidth; int nHeight; char cDatagram[UdpDatagramMaxSize]; }UdpDatagramHead;
Clinet send code
//datagram is QByteArray,whose size is like 0.5~1.5MB int nDataSize = datagram.size(); int nOffset = 0; int nIndex = 0; QByteArray qbtPacket; while (nDataSize > 0) { UdpDatagramHead objUdpHead; objUdpHead.nOffset = nOffset; if (nDataSize > UdpDatagramMaxSize) { qbtPacket = datagram.mid(nOffset, UdpDatagramMaxSize); nOffset += UdpDatagramMaxSize; nDataSize -= UdpDatagramMaxSize; } else { qbtPacket = datagram.mid(nOffset, nDataSize); nOffset += nDataSize; nDataSize = 0; } qDebug() << nIndex; objUdpHead.nDataSize = nDataSize; objUdpHead.nDatagramIndex = nIndex++; objUdpHead.nDatagramSize = qbtPacket.size(); objUdpHead.nIsColor = nIsColor; objUdpHead.nWidth = nWidth; objUdpHead.nHeight = nHeight; memcpy(objUdpHead.cDatagram, qbtPacket.data(), sizeof(char)); nWriteSize = m_pUdpSocket->writeDatagram((char*)&objUdpHead, sizeof(objUdpHead), host, port); m_pUdpSocket->waitForBytesWritten(); qbtPacket.clear(); }
Server recive code:
const int cDataSize = UdpDatagramMaxSize + sizeof(UdpDatagramHead); char cDatagram[cDataSize]; while (m_pUdpSocket->hasPendingDatagrams()) { int nPendingDataSize = m_pUdpSocket->pendingDatagramSize(); m_pUdpSocket->readDatagram(cDatagram, nPendingDataSize); UdpDatagramHead * pUdpHead = (UdpDatagramHead *)cDatagram; if (pUdpHead) { memcpy(m_cImgData + pUdpHead->nOffset, pUdpHead->cDatagram, pUdpHead->nDatagramSize); qDebug() << pUdpHead->nDatagramIndex; if (pUdpHead->nDatagramIndex * UdpDatagramMaxSize + pUdpHead->nDatagramSize == pUdpHead->nDataSize) { uchar * din = (uchar *)m_cImgData; if (pUdpHead->nIsColor) { m_objImg = QImage(din, pUdpHead->nWidth, pUdpHead->nHeight, QImage::Format_RGB888); } else { m_objImg = QImage(din, pUdpHead->nWidth, pUdpHead->nHeight, QImage::Format_Grayscale8); } double dFps = m_objFps.CaculateFps(); emit Signal_ShowImage(pUdpHead->nIsColor, dFps); } } }
Why my reciver packets loss so heavy?
-
Solved by this:
connect(m_pUdpSocket, &QUdpSocket::bytesWritten, this, &QUdpClient::Slot_RefillSocketBuffer);
-
UDP provides no guarantee of delivery, ordering, congestion control, or duplicate protection. Any transient (or permanent) network condition might cause lost packets. In your case it is likely the datagram size exceeds the IP MTU causing datagram fragmentation. If one fragment is lost, then entire datagram is lost.
If you want reliability then use TCP or implement your own re-transmission mechanism
-
UDP provides no guarantee of delivery, ordering, congestion control, or duplicate protection. Any transient (or permanent) network condition might cause lost packets. In your case it is likely the datagram size exceeds the IP MTU causing datagram fragmentation. If one fragment is lost, then entire datagram is lost.
If you want reliability then use TCP or implement your own re-transmission mechanism
@ChrisW67
Actually ive already done one project using Tcp,so now i
m trying to use Udp to make it.
And compare the difference between these two solutions.
Now i need to learn more about Udp and try to establish my own re-transmission mechanism.
For this problem,what kinds of re-transmission mechanism are more suitable?
Others told me to use buffer at reciver which can save every packet,each packet has its own serial number,during some time reciver checks if there are some packets loss.And then send re-transmission.
Or sliding window protocol???
Any advices are benefit for me,
Thanks!!! -
Hi, good you learn about UDP because it is gaining popularity (and TCP is slooooowly going away like FTP or Gopher).
For an implementation of robust and safe transmission over UDP you can look at HTTP/3@hskoglund
Thanks for your advice,i looked HTTP/3 just now,getting it uses Udp instead of Tcp to decrease RTT.
Back to my problem,i still need to solve images are too big to send in one packet but should be cut into plenty of pieces.
So my core question is how sender divide, and how recvier package,and,most important,congestion control and re-transmission.
So complicated for a newbie like me who dont have any experience on client communicates with server. -
Solved by this:
connect(m_pUdpSocket, &QUdpSocket::bytesWritten, this, &QUdpClient::Slot_RefillSocketBuffer);