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. QT with AMQP-CPP library
Forum Updated to NodeBB v4.3 + New Features

QT with AMQP-CPP library

Scheduled Pinned Locked Moved Solved General and Desktop
14 Posts 4 Posters 1.4k Views 2 Watching
  • 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.
  • M Offline
    M Offline
    maragr
    wrote on 18 May 2023, 20:24 last edited by
    #1

    What is the best way to integrate QT QML application to connect with RabbitMQ server using the following library - https://github.com/CopernicaMarketingSoftware/AMQP-CPP

    From high-level description of the library, it seems like a qthandler class that inherits from AMQP::TcpHandler with monitor function needs to be implemented to interact with QT event loop. However, I am unable to use QSocketNotifier to make this work. I am using C++17 and Qt version 5.1.5. Any suggestions?

    M 1 Reply Last reply 19 May 2023, 00:13
    0
    • M maragr
      18 May 2023, 20:24

      What is the best way to integrate QT QML application to connect with RabbitMQ server using the following library - https://github.com/CopernicaMarketingSoftware/AMQP-CPP

      From high-level description of the library, it seems like a qthandler class that inherits from AMQP::TcpHandler with monitor function needs to be implemented to interact with QT event loop. However, I am unable to use QSocketNotifier to make this work. I am using C++17 and Qt version 5.1.5. Any suggestions?

      M Offline
      M Offline
      maragr
      wrote on 19 May 2023, 00:13 last edited by maragr
      #2

      @maragr I was able to get it to work by providing this class as handler to the AMQP::TcpConnection function in main. However, I see that onSocketActivated function is called multiple times by Qt, even though the data is not present on the socket. What is the reason for that and how to resolve this?

      #ifndef MYTCPHANDLER_H
      #define MYTCPHANDLER_H
      
      #include <QObject>
      #include <QSocketNotifier>
      #include <QTcpSocket>
      #include <amqpcpp.h>
      #include <amqpcpp/linux_tcp.h>
      
      class MyTcpHandler : public QObject, public AMQP::TcpHandler
      {
          Q_OBJECT
      public:
          explicit MyTcpHandler(QObject *parent = nullptr);
      
      signals:
      
      private slots:
          void onSocketActivated(int fd, QSocketNotifier::Type flags);
      
      private:
          int m_fd;
          int m_flags;
          AMQP::TcpConnection* _conn;
          QSocketNotifier* socketNotifier;
      
          virtual void monitor(AMQP::TcpConnection* connection, int fd, int flags);
      
          virtual void onError(AMQP::TcpConnection* connection, const char* message);
      };
      
      #endif // MYTCPHANDLER_H
      
      #include "mytcphandler.h"
      
      MyTcpHandler::MyTcpHandler(QObject *parent)
          : QObject{parent}, AMQP::TcpHandler()
      {
      
      }
      
      void MyTcpHandler::onSocketActivated(int fd, QSocketNotifier::Type flags)
      {
          qDebug() << "Reached process";
          _conn->process(fd, AMQP::readable);
      }
      
      void MyTcpHandler::monitor(AMQP::TcpConnection *connection, int fd, int flags)
      {
          qDebug() << "Reached monitor";
          qDebug() << fd;
          m_fd = fd;
          m_flags = flags;
          _conn = connection;
          socketNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read);
          connect(socketNotifier, &QSocketNotifier::activated, this, &MyTcpHandler::onSocketActivated);
          socketNotifier->setEnabled(true);
      }
      
      void MyTcpHandler::onError(AMQP::TcpConnection *connection, const char *message)
      {
          qDebug() << message;
      }
      
      
      C 1 Reply Last reply 19 May 2023, 04:48
      0
      • M maragr
        19 May 2023, 00:13

        @maragr I was able to get it to work by providing this class as handler to the AMQP::TcpConnection function in main. However, I see that onSocketActivated function is called multiple times by Qt, even though the data is not present on the socket. What is the reason for that and how to resolve this?

        #ifndef MYTCPHANDLER_H
        #define MYTCPHANDLER_H
        
        #include <QObject>
        #include <QSocketNotifier>
        #include <QTcpSocket>
        #include <amqpcpp.h>
        #include <amqpcpp/linux_tcp.h>
        
        class MyTcpHandler : public QObject, public AMQP::TcpHandler
        {
            Q_OBJECT
        public:
            explicit MyTcpHandler(QObject *parent = nullptr);
        
        signals:
        
        private slots:
            void onSocketActivated(int fd, QSocketNotifier::Type flags);
        
        private:
            int m_fd;
            int m_flags;
            AMQP::TcpConnection* _conn;
            QSocketNotifier* socketNotifier;
        
            virtual void monitor(AMQP::TcpConnection* connection, int fd, int flags);
        
            virtual void onError(AMQP::TcpConnection* connection, const char* message);
        };
        
        #endif // MYTCPHANDLER_H
        
        #include "mytcphandler.h"
        
        MyTcpHandler::MyTcpHandler(QObject *parent)
            : QObject{parent}, AMQP::TcpHandler()
        {
        
        }
        
        void MyTcpHandler::onSocketActivated(int fd, QSocketNotifier::Type flags)
        {
            qDebug() << "Reached process";
            _conn->process(fd, AMQP::readable);
        }
        
        void MyTcpHandler::monitor(AMQP::TcpConnection *connection, int fd, int flags)
        {
            qDebug() << "Reached monitor";
            qDebug() << fd;
            m_fd = fd;
            m_flags = flags;
            _conn = connection;
            socketNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read);
            connect(socketNotifier, &QSocketNotifier::activated, this, &MyTcpHandler::onSocketActivated);
            socketNotifier->setEnabled(true);
        }
        
        void MyTcpHandler::onError(AMQP::TcpConnection *connection, const char *message)
        {
            qDebug() << message;
        }
        
        
        C Offline
        C Offline
        ChrisW67
        wrote on 19 May 2023, 04:48 last edited by
        #3

        @maragr How many times does your program call MyTcpHandler::monitor()?

        M 1 Reply Last reply 19 May 2023, 17:01
        1
        • C ChrisW67
          19 May 2023, 04:48

          @maragr How many times does your program call MyTcpHandler::monitor()?

          M Offline
          M Offline
          maragr
          wrote on 19 May 2023, 17:01 last edited by maragr
          #4

          @ChrisW67
          Looks like MyTcpHandler::monitor got called 3 times in the beginning with 2 errors and then once it found a successful connection, it doesn't get called again.
          However, the MyTcpHandler::onSocketActivated got called multiple times in the beginning and then "precisely" 6 times before every message. Below is the log.

          QML debugging is enabled. Only use this in a safe environment.
          Reached monitor
          36
          Reached process
          Reached monitor
          40
          Reached monitor
          36
          QSocketNotifier: Invalid socket 36 and type 'Read', disabling...
          Reached process
          Reached process
          QSocketNotifier: Invalid socket 36 and type 'Read', disabling...
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          "amq.ctag-eS23ghYSNLT_UywYko8agg"
          Threaded rendering is not optimal in the Mapbox GL plugin.
          [ INFO ]  "{QSGRenderThread}[General]: GPU Identifier: Mesa Intel(R) UHD Graphics (TGL GT1)"
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          1
          < Print of message 1 body>
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          2
          < Print of message 2 body>
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          Reached process
          .......
          
          SGaistS 1 Reply Last reply 19 May 2023, 18:39
          0
          • M maragr
            19 May 2023, 17:01

            @ChrisW67
            Looks like MyTcpHandler::monitor got called 3 times in the beginning with 2 errors and then once it found a successful connection, it doesn't get called again.
            However, the MyTcpHandler::onSocketActivated got called multiple times in the beginning and then "precisely" 6 times before every message. Below is the log.

            QML debugging is enabled. Only use this in a safe environment.
            Reached monitor
            36
            Reached process
            Reached monitor
            40
            Reached monitor
            36
            QSocketNotifier: Invalid socket 36 and type 'Read', disabling...
            Reached process
            Reached process
            QSocketNotifier: Invalid socket 36 and type 'Read', disabling...
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            "amq.ctag-eS23ghYSNLT_UywYko8agg"
            Threaded rendering is not optimal in the Mapbox GL plugin.
            [ INFO ]  "{QSGRenderThread}[General]: GPU Identifier: Mesa Intel(R) UHD Graphics (TGL GT1)"
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            1
            < Print of message 1 body>
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            2
            < Print of message 2 body>
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            Reached process
            .......
            
            SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on 19 May 2023, 18:39 last edited by
            #5

            Hi,

            That's where your issue lies. You don't delete the previous socket notifier before creating a new one. So you have now three active notifiers.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            M 1 Reply Last reply 19 May 2023, 19:34
            1
            • SGaistS SGaist
              19 May 2023, 18:39

              Hi,

              That's where your issue lies. You don't delete the previous socket notifier before creating a new one. So you have now three active notifiers.

              M Offline
              M Offline
              maragr
              wrote on 19 May 2023, 19:34 last edited by maragr
              #6

              @SGaist So how do I catch any errors and delete the socket notifiers that are not required?

              SGaistS 1 Reply Last reply 19 May 2023, 20:21
              0
              • M maragr
                19 May 2023, 19:34

                @SGaist So how do I catch any errors and delete the socket notifiers that are not required?

                SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on 19 May 2023, 20:21 last edited by
                #7

                You should keep track of the file descriptors and if already in use, don't create a new QSocketNotifier for it.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                M 1 Reply Last reply 20 May 2023, 00:18
                2
                • SGaistS SGaist
                  19 May 2023, 20:21

                  You should keep track of the file descriptors and if already in use, don't create a new QSocketNotifier for it.

                  M Offline
                  M Offline
                  maragr
                  wrote on 20 May 2023, 00:18 last edited by maragr
                  #8

                  @SGaist Not sure if that is the case. Because the QSocketNotifier: Invalid socket 36 and type 'Read', disabling... shows that the invalid socket is disabled. So it might not be firing the activated signal. I printed out the file descriptor when onSocketActivated gets triggered and all of them are called by the same fd. (in this case fd=40). What am I missing?

                  Same behavior is observed even when I keep track of all file descriptors and only create new ones when they are not in use. The only difference with this addition is that now the error QSocketNotifier: Invalid socket 36 and type 'Read', disabling... only appears once.

                  JonBJ 1 Reply Last reply 20 May 2023, 08:50
                  0
                  • M maragr
                    20 May 2023, 00:18

                    @SGaist Not sure if that is the case. Because the QSocketNotifier: Invalid socket 36 and type 'Read', disabling... shows that the invalid socket is disabled. So it might not be firing the activated signal. I printed out the file descriptor when onSocketActivated gets triggered and all of them are called by the same fd. (in this case fd=40). What am I missing?

                    Same behavior is observed even when I keep track of all file descriptors and only create new ones when they are not in use. The only difference with this addition is that now the error QSocketNotifier: Invalid socket 36 and type 'Read', disabling... only appears once.

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on 20 May 2023, 08:50 last edited by
                    #9

                    @maragr
                    Hi. Don't know if I can help butting in. Seems I don't understand what you are asking as well as the others do. Which issue are you trying to address now?

                    • Multiple calls to onSocketActivated() when no data?
                    • Message Invalid socket ...?
                    • Keeping track of which file descriptor numbers you have placed notifiers on?
                    • Something else?
                    M 1 Reply Last reply 20 May 2023, 17:08
                    0
                    • JonBJ JonB
                      20 May 2023, 08:50

                      @maragr
                      Hi. Don't know if I can help butting in. Seems I don't understand what you are asking as well as the others do. Which issue are you trying to address now?

                      • Multiple calls to onSocketActivated() when no data?
                      • Message Invalid socket ...?
                      • Keeping track of which file descriptor numbers you have placed notifiers on?
                      • Something else?
                      M Offline
                      M Offline
                      maragr
                      wrote on 20 May 2023, 17:08 last edited by
                      #10

                      @JonB i am only trying to address why the onSocketActivated function is being called multiple times even when there is no data?

                      (The comments above indicated that it might be an issue with creating many socket notifiers per file descriptor. But resolving this by tracking file descriptors and socket notifiers does not solve the above issue. Hope this helps!)

                      JonBJ 1 Reply Last reply 20 May 2023, 17:58
                      0
                      • M maragr
                        20 May 2023, 17:08

                        @JonB i am only trying to address why the onSocketActivated function is being called multiple times even when there is no data?

                        (The comments above indicated that it might be an issue with creating many socket notifiers per file descriptor. But resolving this by tracking file descriptors and socket notifiers does not solve the above issue. Hope this helps!)

                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on 20 May 2023, 17:58 last edited by JonB
                        #11

                        @maragr
                        OK, now I know where we are :)

                        The QSocketNotifier uses Linux select() call on the file descriptor. I really think you should assume if it says there is a Read data available when it's called there is. Assuming we are indeed not talking about multi-notifiers per descriptor, then I would question how you get your assertion/evidence that no data is there.

                        M 1 Reply Last reply 20 May 2023, 21:33
                        0
                        • JonBJ JonB
                          20 May 2023, 17:58

                          @maragr
                          OK, now I know where we are :)

                          The QSocketNotifier uses Linux select() call on the file descriptor. I really think you should assume if it says there is a Read data available when it's called there is. Assuming we are indeed not talking about multi-notifiers per descriptor, then I would question how you get your assertion/evidence that no data is there.

                          M Offline
                          M Offline
                          maragr
                          wrote on 20 May 2023, 21:33 last edited by maragr
                          #12

                          @JonB Hmm that is a good question. My assertion was based on the fact that onSocketActivated was called 6 times before the consume.onReceived function was triggered from the AMQP-CPP library, thus reading the available message. But now, I think there might be something with this function _conn->process(fd, AMQP::readable); (called within the onSocketActivated slot) from AMQP-CPP library that does not register the read call right away once activated signal is received.

                          Is this a correct assumption that QSocketNotifier will keep triggering the activated signal until the data is read from the socket?

                          JonBJ 1 Reply Last reply 21 May 2023, 07:48
                          0
                          • M maragr
                            20 May 2023, 21:33

                            @JonB Hmm that is a good question. My assertion was based on the fact that onSocketActivated was called 6 times before the consume.onReceived function was triggered from the AMQP-CPP library, thus reading the available message. But now, I think there might be something with this function _conn->process(fd, AMQP::readable); (called within the onSocketActivated slot) from AMQP-CPP library that does not register the read call right away once activated signal is received.

                            Is this a correct assumption that QSocketNotifier will keep triggering the activated signal until the data is read from the socket?

                            JonBJ Offline
                            JonBJ Offline
                            JonB
                            wrote on 21 May 2023, 07:48 last edited by JonB
                            #13

                            @maragr
                            I was about to say "no", I thought it would only raise the signal whenever new data arrived, even if old data was left there presently unread. I believe that is what Qt's normal socket readyRead() behaves:

                            This signal is emitted once every time new data is available for reading from the device. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device

                            However, I am not sure that will be case for QSocketNotifier using select() (or maybe poll()) call. That returns whenever any data is available on a file descriptor (so that a read() will complete), I don't think it would know that new data has arrived rather than old data is already lying there.

                            Unless one or both of these reads the data into a buffer when it first arrives, so that the descriptor is clear for future reads.

                            Truth is I don't know, you would have to test.

                            M 1 Reply Last reply 31 May 2023, 23:48
                            0
                            • JonBJ JonB
                              21 May 2023, 07:48

                              @maragr
                              I was about to say "no", I thought it would only raise the signal whenever new data arrived, even if old data was left there presently unread. I believe that is what Qt's normal socket readyRead() behaves:

                              This signal is emitted once every time new data is available for reading from the device. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device

                              However, I am not sure that will be case for QSocketNotifier using select() (or maybe poll()) call. That returns whenever any data is available on a file descriptor (so that a read() will complete), I don't think it would know that new data has arrived rather than old data is already lying there.

                              Unless one or both of these reads the data into a buffer when it first arrives, so that the descriptor is clear for future reads.

                              Truth is I don't know, you would have to test.

                              M Offline
                              M Offline
                              maragr
                              wrote on 31 May 2023, 23:48 last edited by maragr
                              #14

                              @JonB QSocketNotifier fires until there is data to read on the socket. Marking this as solved.

                              1 Reply Last reply
                              0
                              • M maragr has marked this topic as solved on 31 May 2023, 23:48

                              • Login

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