Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QUdpSocket: has no more pending datagrams
Forum Updated to NodeBB v4.3 + New Features

QUdpSocket: has no more pending datagrams

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 2 Posters 2.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • VRoninV Offline
    VRoninV Offline
    VRonin
    wrote on last edited by
    #2

    can you show us your code? hard to guess for now

    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
    ~Napoleon Bonaparte

    On a crusade to banish setIndexWidget() from the holy land of Qt

    1 Reply Last reply
    1
    • A Offline
      A Offline
      agintz
      wrote on last edited by VRonin
      #3

      Of course, here it is the processPendingDatagram() function:

      ///
      /// \brief AudioUdpRecorder::processPendingDatagrams Fonction appelée à chaque paquet réseau
      /// qui interprète les différents messages.
      ///
      void AudioCoreRecorder::processPendingDatagrams()
      {
          while (udpSocket->hasPendingDatagrams())
      	{
              QByteArray datagram;
      		datagram.resize(udpSocket->pendingDatagramSize());
              qint64 coreMsgByteSize = udpSocket->readDatagram(datagram.data(), datagram.size());
              // Sécurité: on vérifie si le type de message du Core Module existe:
              if (coreMsgByteSize < 1)
              {
                  message.write(Message::WARNING, QString("Received null Core datagram"));
                  return;
              }
              ////////////////////////////////////////////////////////////////////
              // On attend un START pour récupérrer les données du Core Module:
              ////////////////////////////////////////////////////////////////////
              if (getLastCoreRecorderMsgType() == CoreRecorderMsg::STOP)
              {
                  // On informe qu'on n'enregistre pas
                  emit recordingChanged(false);
                  // On interprète le type de message du Core Module:
                  setLastCoreRecorderMsgType(datagram.at(0));
                  message.write(Message::DEBUG, QString("Received Core %1 datagram")
                                .arg(coreRecorderMsgTypeStringMap.value(getLastCoreRecorderMsgType())));
                  /////////////////////////////////////////////////////////////
                  // Il y a 2 possibilités:
                  // o OK: on reçoit un message de type START du Core Module
                  //   --> on répond START,
                  // o KO: on reçoit un autre type de message du Core Module
                  //   --> --
                  /////////////////////////////////////////////////////////////
                  // o OK: on reçoit un message de type START du Core Module
                  //   --> on répond START,
                  //   --> modèle: [uint8 uint8 uint8[256]]
                  if (getLastCoreRecorderMsgType() == CoreRecorderMsg::START)
                  {
                      if (coreMsgByteSize < 2)
                      {
                          message.write(Message::WARNING, QString(" --> Bad channel Core flag"));
                          // datagramMutex.unlock();
                          return;
                      }
                      // On actualise l'état des channels en fonction du channel flag du message du Core Module,
                      // qui informe à son tour l'audioFileRecorder sur le nombre de voies à réceptionner:
                      setChannelFlags(datagram.at(1));
                      // On informe le audioFileRecorder de créer un fichier:
                      audioFileRecorder->wavFileOpen();
                      // On reset les pageIndex de chaque channel pour pouvoir tester la continuité des samples:
                      resetPageIndex();
                      // Si tout va bien, qu'on est prêt, on renvoie le même message
                      emit messageTypeToSend(CoreRecorderMsg::START);
                  }
                  // o KO: on reçoit un autre type de message du Core Module
                  //   --> --
                  else
                  {
                      message.write(Message::WARNING, QString(" --> inapropriate message type: %")
                                    .arg(coreRecorderMsgTypeStringMap[getLastCoreRecorderMsgType()]));
                  }
              }
              ////////////////////////////////////////
              // On attend les data du Core Module:
              ////////////////////////////////////////
              else if (getLastCoreRecorderMsgType() == CoreRecorderMsg::START
                       || getLastCoreRecorderMsgType() == CoreRecorderMsg::DATA)
              {
                  // On interprète le type de message du Core Module:
                  setLastCoreRecorderMsgType(datagram.at(0));
                  /////////////////////////////////////////////////////////////
                  // Il y a 3 possibilités:
                  // o OK: on reçoit un message de type DATA du Core Module
                  //   --> on enregistre les DATA,
                  // o OK: on reçoit un message de type STOP du Core Module
                  //   --> on répond STOP,
                  // o KO: on reçoit un message de type START du Core Module
                  //   --> on répond START,
                  // o KO: on reçoit un autre type de message du Core Module
                  //   --> --,
                  /////////////////////////////////////////////////////////////
                  // o OK: on reçoit un message de type DATA du Core Module
                  //   --> on enregistre les DATA,
                  //   --> modèle: [uint8 uint8 uint16 uint32 uint16[512]],
                  if (getLastCoreRecorderMsgType() == CoreRecorderMsg::DATA)
                  {
                      if (coreMsgByteSize < 2)
                      {
                          // On informe qu'on n'enregistre pas
                          emit recordingChanged(false);
                          message.write(Message::WARNING, QString(" --> Bad Core channel flag"));
                          // datagramMutex.unlock();
                          return;
                      }
                      // Sécurité ?????:
                      ushort sharedVectorSizeShort = ushort(coreMsgByteSize-CORE_MODULE_OFFSET_DATA)/2; // Taille un short ;-)
                      if (coreMsgByteSize < CORE_MODULE_DATA_SIZE)
                      {
                          message.write(Message::DEBUG, QString(" --> incomplete data frame?"));
                      }
                      ///////////////////////////////////////
                      // on acquiert les données (16 bits):
                      ///////////////////////////////////////
                      // On informe qu'on enregistre
                      emit recordingChanged(true);
                      // On pointe sur le 8 ème élément (arithmétique de pointeurs),
                      // la où commencent le sample frame:
                      const ushort *ptr =
                              reinterpret_cast<const ushort*>(datagram.constData()+CORE_MODULE_OFFSET_DATA);
                      ///////////////////////////////////
                      // THREAD CONCURRENCY MANAGEMENT //
                      // o    Prend un jeton pour Fill (nécessite qu'un jeton ait été libéré
                      //      par le wavRecorder)
                      bufferFilling.acquire(1);
                      // On actualise l'état des channels en fonction du channel flag du message du Core Module
                      // qui prévient également l'audioFileRecorder du numéro de la voie.
                      // NOTE: il est important d'informer l'audioFileRecorder APRES le semaphore pour qu'il reste
                      // identique dans la phase de "filling" et la phase de "Recording".
                      setChannelOnTheAir(datagram.at(1));
                      // Test de continuité des DATA: les indexes doivent être consécutifs, sans quoi on perd des données...
                      if (!updateActualPageIndex(datagram.mid(CORE_MODULE_OFFSET_INDEX,4)))
                          message.write(Message::ERROR, QString(" --> samples not successive"));
                      // DEBUG:
                      message.write(Message::DEBUG, QString("%1/%2/%3/%4")
                                    .arg(getPageIndexList().at(0))
                                    .arg(getPageIndexList().at(1))
                                    .arg(getPageIndexList().at(2))
                                    .arg(getPageIndexList().at(3)));
                      ///////////////////////////////////
                      if (getChannelOnTheAir() == 0)
                      {
                          // On remplit le buffer avec les samples:
                          for (ushort i = 0; i < sharedVectorSizeShort; i++)
                              sharedVectorChannel0[i] = *(ptr+i); // Arithmetique de pointeurs
                          // On met à 0 les non remplis:
                          for (ushort i = sharedVectorSizeShort; i < CORE_MODULE_BUFFER_SIZE; i++)
                              sharedVectorChannel0[i] = 0; // Arithmetique de pointeurs
                      }
                      if (getChannelOnTheAir() == 1)
                      {
                          // On remplit le buffer:
                          for (ushort i = 0; i < sharedVectorSizeShort; i++)
                              sharedVectorChannel1[i] = *(ptr+i); // Arithmetique de pointeurs
                          for (ushort i = sharedVectorSizeShort; i < CORE_MODULE_BUFFER_SIZE; i++)
                              sharedVectorChannel1[i] = 0; // Arithmetique de pointeurs
                      }
                      if (getChannelOnTheAir() == 2)
                      {
                          // On remplit le buffer:
                          for (ushort i = 0; i < sharedVectorSizeShort; i++)
                              sharedVectorChannel2[i] = *(ptr+i); // Arithmetique de pointeurs
                          for (ushort i = sharedVectorSizeShort; i < CORE_MODULE_BUFFER_SIZE; i++)
                              sharedVectorChannel2[i] = 0; // Arithmetique de pointeurs
                      }
                      if (getChannelOnTheAir() == 3)
                      {
                          // On remplit le buffer:
                          for (ushort i = 0; i < sharedVectorSizeShort; i++)
                              sharedVectorChannel3[i] = *(ptr+i); // Arithmetique de pointeurs
                          for (ushort i = sharedVectorSizeShort; i < CORE_MODULE_BUFFER_SIZE; i++)
                              sharedVectorChannel3[i] = 0; // Arithmetique de pointeurs
                      }
                      ///////////////////////////////////
                      // THREAD CONCURRENCY MANAGEMENT //
                      // o     Rend un jeton pour Record
                      bufferRecording.release(1);
                      ///////////////////////////////////
                  }
                  // o OK: on reçoit un message de type STOP du Core Module
                  //   --> on répond STOP,
                  else if (getLastCoreRecorderMsgType() == CoreRecorderMsg::STOP)
                  {
                      message.write(Message::DEBUG, QString("Received Core %1 datagram")
                                    .arg(coreRecorderMsgTypeStringMap.value(getLastCoreRecorderMsgType())));
                      // On informe qu'on n'enregistre pas
                      emit recordingChanged(false);
                      // On ferme le fichier:
                      audioFileRecorder->wavFileClose();
                  }
                  // o KO: on reçoit un message de type START du Core Module
                  //   --> on répond START,
                  else if (getLastCoreRecorderMsgType() == CoreRecorderMsg::START)
                  {
                      message.write(Message::DEBUG, QString("Received Core %1 datagram")
                                    .arg(coreRecorderMsgTypeStringMap.value(getLastCoreRecorderMsgType())));
                      // On informe qu'on n'enregistre pas
                      emit recordingChanged(false);
                      // On indique que c'est pas normal:
                      message.write(Message::WARNING, QString(" --> Unexpected because already recording"));
                      if (coreMsgByteSize < 2)
                      {
                          message.write(Message::WARNING, QString(" --> Bad channel Core flag"));
                          // datagramMutex.unlock();
                          return;
                      }
                      setLastCoreRecorderMsgType(datagram.at(0));
                      // On actualise l'état des channels en fonction du channel flag  du message du Core Module:
                      setChannelFlags(datagram.at(1));
                      // Si tout va bien, qu'on est prêt, on renvoie le même message
                      emit messageTypeToSend(CoreRecorderMsg::START);
                  }
                  // o KO: on reçoit un autre type de message du Core Module
                  //   --> --
                  else
                  {
                      message.write(Message::DEBUG, QString("Received Core %1 datagram")
                                    .arg(coreRecorderMsgTypeStringMap.value(getLastCoreRecorderMsgType())));
                      // On informe qu'on n'enregistre pas
                      emit recordingChanged(false);
                      message.write(Message::WARNING, QString(" --> inapropriate message type: %")
                                    .arg(coreRecorderMsgTypeStringMap[getLastCoreRecorderMsgType()]));
                  }
              }
          }
          message.write(Message::DEBUG, QString("exit()"));
      }
      

      AG

      1 Reply Last reply
      0
      • A Offline
        A Offline
        agintz
        wrote on last edited by VRonin
        #4

        Sorry for my last post. Here I post a new one with a simple test which lead to the same problem:

        main

        #include <QCoreApplication>
        #include <QDebug>
        #include "socketmanager.h"
        
        int main(int argc, char *argv[])
        {
            QCoreApplication a(argc, argv);
            SocketManager coreModule;
            coreModule.bind();
        
            return a.exec();
        }
        
        **socketmanager.h**
        #ifndef SOCKETMANAGER_H
        #define SOCKETMANAGER_H
        
        #include <QObject>
        #include <QDebug>
        #include <QUdpSocket>
        #include <QThread>
        
        class SocketManager: public QObject
        {
            Q_OBJECT
        public:
                                SocketManager();
            QUdpSocket          *udpSocket;
            bool                started;
            unsigned int        count;
        
            void                bind();
        public slots:
            void                processPendingDatagrams();
            void                sendPendingDatagrams();
        };
        
        #endif // SOCKETMANAGER_H
        

        socketmanager.cpp

        #include "socketmanager.h"
        
        SocketManager::SocketManager()
        {
            started = false;
            count = 0;
            udpSocket = new QUdpSocket;
        }
        
        
        void SocketManager::bind()
        {
            qDebug() << "Wait for binding";
            connect(udpSocket,SIGNAL(readyRead()), this,SLOT(processPendingDatagrams()));
            while(!udpSocket->bind(QHostAddress("192.168.1.167"),8998))
            {
                QThread::currentThread()->msleep(1000);
            }
        
            qDebug() << "Binded";
        }
        
        void SocketManager::processPendingDatagrams()
        {
            while (udpSocket->hasPendingDatagrams())
            {
                QByteArray datagram;
                datagram.resize(udpSocket->pendingDatagramSize());
                qint64 coreMsgByteSize = udpSocket->readDatagram(datagram.data(), datagram.size());
                if (!started)
                {
                    sendPendingDatagrams();
                    qDebug() << "Started";
                    started = true;
                    return;
                }
                if (coreMsgByteSize > 500)
                {
                    count++;
                    if (count%4 == 0)
                        qDebug() << count/4;
                }
            }
        }
        
        
        void SocketManager::sendPendingDatagrams()
        {
            QByteArray block;
            block.append(char(0x40));
            block.append(char(0x0F));
            block.append(char(0xFF));   // Ici on configure le temps d'enregistrement sur
            block.append(char(0xFF));   // 4 octets, pour l'instant on met le max!
            block.append(char(0xFF));
            block.append(char(0xFF));
            if (udpSocket->writeDatagram(block,
                                         QHostAddress("192.168.1.166"), 8888) < 0)
            {
                qDebug() << "Failed to send datagram";
            }
            else
            {
                qDebug() << "Datagram sent";
            }
        }
        

        Result
        The last console output is (always, whatever the test): 11402

        Thank you

        AG

        1 Reply Last reply
        0
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #5

          Could you try to change if (coreMsgByteSize > 500) to if (coreMsgByteSize > 0)

          You are leaking the socket. udpSocket = new QUdpSocket; should be udpSocket = new QUdpSocket(this);

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          1 Reply Last reply
          1
          • A Offline
            A Offline
            agintz
            wrote on last edited by
            #6

            Hi VRonin,

            Given that this code is a simple test, I do quickly and then bad, so leaks... ;-)
            Anyway, I first made a filter with "if (coreMsgByteSize > 500)" because the first datagram from the device is of size 30 bytes whereas the audio stream datagrams are of size 1032 bytes.

            I will do changes on monday.

            I have seen several QtBugs about QUdpSocket: bug1, bug2 around Qt version I use. Although I updated Qt version from 5.5.1 to 5.6.2 to check if it could be the solution, but... no.

            AG

            1 Reply Last reply
            0
            • A Offline
              A Offline
              agintz
              wrote on last edited by
              #7

              Hi,

              here is the console output from the last code, with change from if (coreMsgByteSize > 500) to if (coreMsgByteSize > 0) :
              Wait for binding
              Binded
              Datagram sent
              Started
              1
              2
              3
              4
              ...
              11400

              AG

              1 Reply Last reply
              0
              • VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by VRonin
                #8

                So very bizarre...

                • Could you try with Qt 5.11 and see if it's the same?
                • In SocketManager::bind() could you add, as first line:
                QTimer* backupTimer = new QTimer(this);
                connect(backupTimer,&QTimer::timeout,this,&SocketManager::processPendingDatagrams);
                backupTimer->start(2000);
                

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                A 1 Reply Last reply
                0
                • A Offline
                  A Offline
                  agintz
                  wrote on last edited by
                  #9

                  In my last test, my device sent me 4 audio channels, each datagram representing a 512 samples buffer from one channel.
                  I just have done a test with only one channel, that means each datagram is from the channel one, now. The recording stops at the same iteration, but after 4 times more time. The console output is now:
                  Wait for binding
                  Binded
                  Datagram sent
                  Started
                  1
                  2
                  3
                  4
                  ...
                  11401

                  AG

                  1 Reply Last reply
                  0
                  • VRoninV VRonin

                    So very bizarre...

                    • Could you try with Qt 5.11 and see if it's the same?
                    • In SocketManager::bind() could you add, as first line:
                    QTimer* backupTimer = new QTimer(this);
                    connect(backupTimer,&QTimer::timeout,this,&SocketManager::processPendingDatagrams);
                    backupTimer->start(2000);
                    
                    A Offline
                    A Offline
                    agintz
                    wrote on last edited by
                    #10

                    @VRonin said in QUdpSocket: has no more pending datagrams:

                    Could you try with Qt 5.11 and see if it's the same?
                    In SocketManager::bind() could you add, as first line:

                    I tried on Ubuntu with Qt5.6 & 5.11 and on Win10 with Qt5.6:

                    • On Ubuntu the iteration stops at 11402 whatever the Qt version
                    • On Win10 the iteration stops with a random number (between 300 and 400).

                    I also used your timer to trigger the processPendingDatagrams() function but it seems that udpSocket->hasPendingDatagrams() return false because nothing happens.

                    AG

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      agintz
                      wrote on last edited by
                      #11

                      Hello, hello,

                      I have tried to manage the audio stream with another library (ASIO) and the result is the same as I got with QtNetwork. I conclude the problem comes from the device, not from the software I develop.

                      Sorry for wasting your time and thank you for trying to help me...

                      AG

                      1 Reply Last reply
                      1

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved