QUdpsocket在处理前一个数据报时会丢失数据报

时间:2016-04-06 21:02:38

标签: c++ qt sockets networking udp

我通过udp分割帧(50Kb)并将frameId添加到数据,从一个应用程序(统一)向另一个应用程序(QT)发送未打包的图像(bmp)数据。 另一方面,我正在尝试集成帧(使用frameId),在我收集了一个图像的所有帧后,我将其处理为图像。 如果我只是捕捉框架而不处理它们我正在以正确的顺序获取数据

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);
    }
}

我在控制台看到“1 2 3 4 5 1 2 3 4 5 1 2 3 4 5” 但如果我取消注释processTheDatagram(数据报); 我得到“1 3 4 1 2 4 2 4 5 2 3 5” 它在处理先前的数据报时会丢失数据。 问题出在哪儿?? 在udp缓冲区?

2 个答案:

答案 0 :(得分:5)

  

问题出在哪里?在udp缓冲区?

问题是如果套接字的recv-buffer填满,那么当缓冲区已满时计算机收到的任何UDP数据包都将被丢弃。这不是一个错误,它是一个&#39;功能&#39; UDP的工作原理。

丢弃的UDP数据包只是生活中的一个事实;任何使用UDP的程序都必须以某种方式处理丢弃的UDP数据包。以下是一些可以处理它们的方法(并非所有相互排斥的方式):

  1. 使您的processTheDatagram()函数如此高效,以至于它总是返回足够快以至于UDP缓冲区永远没有时间填满
  2. 在QUDPSocket上调用setSocketOption(QAbstractSocket :: ReceiveBufferSizeSocketOption,someLargeValue),为其提供更大的内核接收缓冲区,这将需要更长的时间才能填满
  3. 不要试图在同一个线程中处理数据报,只需将数据报添加到FIFO队列中,让另一个线程完成繁重的工作。这样,您的I / O线程可以随时快速接收下一个UDP数据包。
  4. 实施某种流量控制或数据包重发算法,这样数据包就不会比计算机处理它们更快地发送,或者如果数据包被丢弃,您可以请求再次发送数据包(虽然如果沿着这条路走下去,通常最好只使用TCP)
  5. 在更快的计算机上运行:)

答案 1 :(得分:0)

作为@Jeremy Friesner的第二项建议的补充:

对于QUdpSocket:

  1. 确保您调用setSocketOption而不是setReadBufferSize,后者引用了QAbstractSocket的内部缓冲区QUdpSocket不使用。
  2. 在setSocketOption之前调用QUdpSocket :: bind。