Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-138379

QUdpSocket in a dedicated thread fails to receive packets under high traffic from another thread

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 6.9.1
    • Network: Sockets
    • None
    • Windows
    • Windows

    Description

      Description :

      A QUdpSocket running in its own dedicated QThread is unable to receive any UDP multicast packets when a separate thread in the same application is handling a high-traffic (e.g., 200 Mbps) UDP multicast stream on a different port.

      This issue is fully load-dependent. The command response is received perfectly when the high-traffic stream is not active.

      Wireshark confirms the response packet is successfully delivered to the PC's network interface, but the application's readyRead signal for the command socket is never emitted.

      Extensive debugging has ruled out application-level issues such as thread starvation, firewall blocks, incorrect network interface selection, response timeouts, and socket buffer sizes. The issue persists even in the minimal reproducible example provided below.

      This suggests a potential bug or limitation in Qt's socket notifier or the OS networking layer's ability to handle this specific multi-threaded, high-load scenario.

      Steps to Reproduce:

      1. Create a "Qt Console Application" project.
      1. Use the attached main.cpp and .pro file.
      1. Start a high-traffic UDP multicast stream (approx. 200 Mbps) directed at the HIGH_TRAFFIC_PORT.
      1. Trigger an external device to send a single UDP multicast response packet to the COMMAND_LISTEN_PORT.

       

      Actual Results (实际结果): The application receives the high-traffic stream correctly, but the readyRead signal for the COMMAND_LISTEN_PORT socket is never emitted, and the response packet is never received by the application.

      Expected Results (期望结果): Both sockets should receive their respective packets independently, and the "SUCCESS! Packet Received" message should be printed.

      Minimal Reproducible Example (最小可复现示例):

      • *.pro file:*
        Code snippet
        {{QT += core network }}
        CONFIG = c+17 cmdline
        {{ SOURCES += main.cpp}}
      • *main.cpp file:* 
      • #include <QCoreApplication>
        #include <QThread>
        #include <QUdpSocket>
        #include <QNetworkInterface>
        #include <QDebug>
        #include <QTimer>
        #include <QNetworkDatagram>

      const QHostAddress MULTICAST_GROUP_ADDRESS("234.5.4.110");
      const quint16 HIGH_TRAFFIC_PORT = 8010; 
      const quint16 COMMAND_LISTEN_PORT = 8000;  

      class HighTrafficReceiver : public QObject
      {
          Q_OBJECT
      public slots:
          void start() {
              qDebug() << "[Traffic Thread] Starting on thread:" << QThread::currentThread();
              socket = new QUdpSocket(this);

              if (!socket->bind(QHostAddress::AnyIPv4, HIGH_TRAFFIC_PORT, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint))

      {             qWarning() << "[Traffic Thread] Failed to bind high traffic port:" << socket->errorString();             return;         }

              bool joined = socket->joinMulticastGroup(MULTICAST_GROUP_ADDRESS);
              qDebug() << "[Traffic Thread] Joined multicast group:" << joined;

              connect(socket, &QUdpSocket::readyRead, this, &HighTrafficReceiver::onReadyRead);
              qDebug() << "[Traffic Thread] Now listening for high traffic on port" << HIGH_TRAFFIC_PORT;
          }

      private slots:
          void onReadyRead() {
              while (socket->hasPendingDatagrams())

      {             socket->receiveDatagram();             m_packetCount++;         }

          }

      public:
          quint64 packetCount() const { return m_packetCount; }

      private:
          QUdpSocket* socket;
          quint64 m_packetCount = 0;
      };

      class CommandReceiver : public QObject
      {
          Q_OBJECT
      public slots:
          void start() {
              qDebug() << "[Command Thread] Starting on thread:" << QThread::currentThread();
              socket = new QUdpSocket(this);

              if (!socket->bind(QHostAddress::AnyIPv4, COMMAND_LISTEN_PORT, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint))

      {             qWarning() << "[Command Thread] Failed to bind command port:" << socket->errorString();             return;         }

              bool joined = socket->joinMulticastGroup(MULTICAST_GROUP_ADDRESS);
              qDebug() << "[Command Thread] Joined multicast group:" << joined;

              connect(socket, &QUdpSocket::readyRead, this, &CommandReceiver::onReadyRead);
              qDebug() << "[Command Thread] Now listening for command response on port" << COMMAND_LISTEN_PORT;
          }

      signals:
          void packetSuccessfullyReceived();

      private slots:
          void onReadyRead() {
              if (socket->hasPendingDatagrams())

      {             qDebug() << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";             qDebug() << "!!! [Command Thread] SUCCESS! Packet Received on port" << COMMAND_LISTEN_PORT;             qDebug() << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";             emit packetSuccessfullyReceived();         }

          }
      private:
          QUdpSocket* socket;
      };

      int main(int argc, char *argv[])
      {
          QCoreApplication a(argc, argv);

          qDebug() << "Starting UDP Stress Test...";

          QThread* trafficThread = new QThread(&a);
          HighTrafficReceiver* trafficReceiver = new HighTrafficReceiver();
          trafficReceiver->moveToThread(trafficThread);
          QObject::connect(trafficThread, &QThread::started, trafficReceiver, &HighTrafficReceiver::start);
          trafficThread->start();

          QThread* commandThread = new QThread(&a);
          CommandReceiver* commandReceiver = new CommandReceiver();
          commandReceiver->moveToThread(commandThread);
          QObject::connect(commandThread, &QThread::started, commandReceiver, &CommandReceiver::start);
          QObject::connect(commandReceiver, &CommandReceiver::packetSuccessfullyReceived, &a, &QCoreApplication::quit);
          commandThread->start();

          QTimer statusTimer(&a);
          QObject::connect(&statusTimer, &QTimer::timeout, [&]()

      {         qDebug() << "[Status] High traffic packets received so far:" << trafficReceiver->packetCount();     }

      );
          statusTimer.start(5000);

          qDebug() << "\nSetup complete. The application is now running.";
          qDebug() << "Please ensure the 200Mbps data stream is active.";
          qDebug() << "Then, manually trigger a command on your device to send a response to port" << COMMAND_LISTEN_PORT;
          qDebug() << "Waiting for command response...\n";

          return a.exec();
      }

      #include "main.moc"

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            manordheim Mårten Nordheim
            tushan 杰屹 邹
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes