Аскер Чик
Аскер Чик

Reputation: 53

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?

Upvotes: 3

Views: 3193

Answers (2)

John Gilbert
John Gilbert

Reputation: 21

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.

Upvotes: 2

Jeremy Friesner
Jeremy Friesner

Reputation: 73041

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 :)

Upvotes: 7

Related Questions