QUdpsocket丢失数据报,同时处理前一个

Аск*_*Чик 1 c++ sockets networking qt udp

我通过udp分割帧(50Kb)并将frameId添加到数据中,将未打包的图像(bmp)数据从一个应用程序(联合)发送到另一个(QT)。另一方面,我试图集成框架(使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Jer*_*ner 5

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

问题在于,如果套接字的recv缓冲区已满,则当缓冲区已满时计算机收到的所有UDP数据包都会被丢弃。这不是错误,而是UDP工作原理的“特征”。

丢弃的UDP数据包只是生活中的事实。使用UDP的任何程序都必须以一种或另一种方式处理丢弃的UDP数据包。您可以通过以下几种方式来处理它们(并非全部互斥):

  1. 提高您的processTheDatagram()函数的效率,使其总是返回足够快的速度,以至于UDP缓冲区再也没有时间来填满
  2. 在QUDPSocket上调用setSocketOption(QAbstractSocket :: ReceiveBufferSizeSocketOption,someLargeValue)给它更大的内核接收缓冲区,这将花费更长的时间来填充
  3. 无需尝试在同一线程中处理数据报,只需将数据报添加到FIFO队列中,然后让另一个线程完成繁重的工作即可。这样,您的I / O线程始终可以自由地快速接收下一个UDP数据包。
  4. 实现某种流控制或数据包重发算法,以使数据包的发送不会比计算机处理数据包的速度快,或者使数据包丢失时,您可以请求再次发送数据包(尽管如果失败,这种方式通常最好使用TCP代替)
  5. 在更快的计算机上运行:)