Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QUdpsocket losses datagrams while processing previous one

Im sending not packed image (bmp) data from one application(unity) to another (QT) via udp splitting in frames (50Kb) and adding frameId to data. On other side I'm trying to integrate frames (using frameId) and after i collected all frames of one image I process it as image. If Im just catching frames and do not process them Im getting data in right sequence

void Server::readPendingDatagrams()
{
    if (udpSocket->hasPendingDatagrams()) {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        QHostAddress sender;
        quint16 senderPort;

        udpSocket->readDatagram(datagram.data(), datagram.size(),
                                &sender, &senderPort);
        qDebug()<<datagram[0]; //frameId
        //processTheDatagram(datagram);
    }
}

I see "1 2 3 4 5 1 2 3 4 5 1 2 3 4 5" in console but if I uncomment processTheDatagram(datagram); I'm getting "1 3 4 1 2 4 2 4 5 2 3 5" it losses data while processing previous datagram. Where is the problem?? in udp buffer?

like image 298
Аскер Чик Avatar asked Nov 17 '25 11:11

Аскер Чик


2 Answers

Where is the problem?? in udp buffer?

The problem is that if the socket's recv-buffer fills up, then any UDP packets the computer receives while the buffer is full will be dropped. That's not a bug, it's a 'feature' of how UDP works.

Dropped UDP packets are just a fact of life; any program that uses UDP has to deal with dropped UDP packets one way or another. Here are some ways you could deal with them (not all mutually exclusive):

  1. Make your processTheDatagram() function so efficient that it always returns fast enough that the UDP buffer never has time to fill up
  2. Call setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, someLargeValue) on your QUDPSocket to give it a bigger in-kernel receive buffer, which will take longer to fill up
  3. Instead of trying to process the datagram in the same thread, just add the datagram to a FIFO queue and let another thread do the heavy lifting. That way your I/O thread is always free to quickly receive the next UDP packet.
  4. Implement some sort of flow-control or packet-resend algorithm so that packets won't be sent faster than your computer can process them, or so that if a packet is dropped you can request to have it sent again (although if you go down this route it's often better to just use TCP instead)
  5. Run on a faster computer :)
like image 148
Jeremy Friesner Avatar answered Nov 20 '25 03:11

Jeremy Friesner


As a complement to @Jeremy Friesner 's second recommendation:

For QUdpSocket:

  1. Make sure you call setSocketOption instead of setReadBufferSize which refers to QAbstractSocket's internal buffer QUdpSocket doesn't use.
  2. Call QUdpSocket::bind before setSocketOption.
like image 37
John Gilbert Avatar answered Nov 20 '25 05:11

John Gilbert



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!