Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. General talk
  3. Qt 6
  4. QtcpSocket instantiation not morking properly
Forum Updated to NodeBB v4.3 + New Features

QtcpSocket instantiation not morking properly

Scheduled Pinned Locked Moved Solved Qt 6
9 Posts 3 Posters 1.0k Views 1 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.
  • B Offline
    B Offline
    beHa
    wrote on last edited by
    #1

    Hello Sirs,
    i'm quite starting OOP so i can make incredible stupid things. Anyway. I've got 2 cameras (or 4) witch own their tcp server for providing MJPEG video stream. on one base computer i need to handle 2 (or 4) tcp client connections to these units. if i just have one instance, or one camera to handle, it works. but with multiple, it fail in bad tcp connections, I my mind, the issue should be with the instanciation of 2 QTcpsocket objects. I tried with thread, with slots, still the same, when i instanciate more than one object of my client class, the connection read nothing or auto close. I have different TCP port for different units before you tell that. have a look on my main code sirs:

    The main entry:

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include <QDebug>
    #include <QImage>
    #include <QThread>
    #include "streamerslot.h"
    #include "streamerslot2.h"
    #include "camimageprovider.h"
    
    
    //#include "streamerclient.h"
    //#include "streamerthread.h"
    //#include "streamerthread2.h"
    
    #include<unistd.h>
    int main(int argc, char *argv[])
    {
    
        QGuiApplication app(argc, argv);
    
    
           streamerSlot clientSat1(1238,"SAT1-SNTL");
           streamerSlot clientSat2(1234,"SAT2-SNTL");
       
        clientSat2.test();
       clientSat1.test();
       
        CamImageProvider *camImageProviderSat1(new CamImageProvider());
        CamImageProvider *camImageProviderSat2(new CamImageProvider());
        QQmlApplicationEngine engine;
    
    
        engine.rootContext()->setContextProperty("camImageProviderSat1",camImageProviderSat1);
        engine.addImageProvider("camSat1", camImageProviderSat1);
    
        engine.rootContext()->setContextProperty("camImageProviderSat2",camImageProviderSat2);
        engine.addImageProvider("camSat2", camImageProviderSat2);
    
        const QUrl url(u"qrc:/baseApp001/main.qml"_qs);
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                           &app, [url](QObject *obj, const QUrl &objUrl) {
              if (!obj && url == objUrl)
                  QCoreApplication::exit(-1);
          }, Qt::QueuedConnection);
        engine.load(url);//const QImage &)) ,Qt::DirectConnection
    
    
        QObject::connect(&clientSat1, SIGNAL(newImage(QImage)),camImageProviderSat1,  SLOT(updateImage(QImage)));
        QObject::connect(&clientSat2, SIGNAL(newImage(QImage)),camImageProviderSat2,  SLOT(updateImage(QImage)));
        //QObject::connect(&clientSat1, SIGNAL(bridgenewImage(QImage)),camImageProviderSat1,  SLOT(updateImage(QImage)));
        //QObject::connect(&clientSat2, SIGNAL(bridgenewImage(QImage)),camImageProviderSat2,  SLOT(updateImage(QImage)));
        if (engine.rootObjects().isEmpty())
              return -1;
    
          return app.exec();
    }
    
    
    

    The connectToServer classe:

    #ifndef STREAMERSLOT_H
    #define STREAMERSLOT_H
    
    #include <QObject>
    #include <QDebug>
    #include<QTcpsocket>
    #include<QAbstractsocket>
    #include<QImage>
    #include <opencv2/core.hpp>
    class streamerSlot : public QObject
    {
        Q_OBJECT
    public:
        explicit streamerSlot(int port,char *satName,QObject *parent = nullptr);
        void test();
    signals:
         void newImage(const QImage &);
    public slots:
        void connected();
        void disconnected();
        void bytesWritten (qint64 bytes);
        void readyRead();
    
    private:
        QTcpSocket *socket;
        QImage m_Image;
        char m_satName[16];
        int m_satPort=0;
        QImage Mat2QImage(cv::Mat const& src);
        cv::Mat QImage2Mat(QImage const& src);
          QDataStream in;
          char _datout=0;
          int n=0;
    };
    
    #endif // STREAMERSLOT_H
    

    And its declaration:

    #include "streamerslot.h"
    #include<iostream>
    #include<QImage>
    #include<QDebug>
    #include <iostream>
    #include <opencv2/core.hpp>
    #include <opencv2/videoio.hpp>
    #include <opencv2/highgui.hpp>
    #include<opencv2/imgproc.hpp>
    #include <unistd.h>
    
    //QDataStream in(socket);
    QImage streamerSlot::Mat2QImage(cv::Mat const& src)
    {
    
        cv::Mat temp; //make the same cv::Mat
        cvtColor(src, temp,cv::COLOR_BGR2RGB); //cvtColor Makes a copt, that what i need
        QImage dest((const uchar *) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
        dest.bits(); //enforce deep copy, see documentation
        return dest;
    }
    cv::Mat streamerSlot::QImage2Mat(QImage const& src)
    {
        cv::Mat tmp(src.height(),src.width(),CV_8UC3,(uchar*)src.bits(),src.bytesPerLine());
        cv::Mat result; //deep copy just in case (my lack of knowledge with open cv)
        cvtColor(tmp, result,cv::COLOR_BGR2RGB);
        return result;
    }
    streamerSlot::streamerSlot(int port,char *satName,QObject *parent)
        : QObject{parent}
    {
        m_satPort=port;
      strcpy(m_satName,satName);
    
         //m_Image = QImage(640,480, QImage::Format_RGB888);//RGB32);
          m_Image = QImage(1280,720, QImage::Format_RGB888);//RGB32);
    }
    
    void streamerSlot::test()
    {
        socket=new QTcpSocket(this);
        connect(socket,SIGNAL(connected()),this,SLOT(connected()));
        connect(socket,SIGNAL(disconnected()),this,SLOT(disconnected()));
        connect(socket,SIGNAL(readyRead()),this,SLOT(readyRead()),Qt::QueuedConnection);
        connect(socket,SIGNAL(bytesWritten(qint64 )),this,SLOT(bytesWritten(qint64 )));
    
        qDebug()<<"connecting..";
        socket->connectToHost(m_satName,m_satPort);// "SAT1-SNTL",1238);
        n=m_satPort;
        if(!socket->waitForConnected(3000))
        {
            qDebug()<<"error"<<socket->errorString();
        }
        in.setDevice(socket);
        in.setVersion(QDataStream::Qt_5_11);
        in.startTransaction();
    }
    void streamerSlot::connected()
    {
    qDebug()<<"connected..";
    }
    void streamerSlot::disconnected()
    {
    qDebug()<<"disconnected..";
    }
    void streamerSlot::bytesWritten(qint64 bytes)
    {
        qDebug()<<"wrote..";
    }
    void streamerSlot::readyRead()
    {
    //  QImage image;
      QByteArray      data;
      static qint64 imageSize = 0;
      QString currentSatName="";
      QByteArray currentSatData;
    
    
    //depart de trame , on recoit la taille, le nom du sat et les data params(SNTL)
          if ( 0 == imageSize ) {
              if ( socket->bytesAvailable() < (int)sizeof(qint64) ) return;
              in >> imageSize;
              in>>currentSatName;
              in>>currentSatData;
    
           //   qDebug()<<"reading.."<<n<<" " << imageSize<<"  "<<currentSatName<<"  "<<currentSatData;
    
          }
    //si on a pas encore la taille necessaire on quitte
          if ( socket->bytesAvailable() < imageSize ) return;
    //une fois qu'on l'a, on charge
          in>>data;
    // et on traite Vers cv::Mat:
          std::vector<uchar> vData(data.begin(), data.end());
          cv::Mat matImg;
          if(imageSize!=-1&&imageSize!=0&&data.size()>0)
          {
            matImg = cv::imdecode(cv::Mat(1,imageSize,CV_8UC1,&vData[0]), cv:: IMREAD_COLOR);
            QImage image= Mat2QImage(matImg);
            emit newImage(image);
           // socket->flush();
          }
    //Si on a un soucis eventuel, on vide tout
          else
          {
            qDebug()<<"matrice a -1 "<<this<< " :erreur decodage tcp";;
            QImage image = QImage(640,480, QImage::Format_RGB888);
            image.fill(QColor("red"));
            socket->flush();
          }
          imageSize = 0;
    }
    
    

    if i create in main 2 streamerSlot object, the communication is crashing by hangling in the

    qDebug()<<"matrice a -1 "<<this<< " :erreur decodage tcp";;
    

    on camera server side, the connection opened and it stared to emit and it stopped
    BUT, if i copy the streamerslot.cpp& streamerslot.h to a streamerslot2.cpp& streamerslot2.h and i instantiate as this:

    streamerSlot clientSat1(1238,"SAT1-SNTL");
           streamerSlot2 clientSat2(1234,"SAT2-SNTL");
    

    It works....connection is up and running....too stupid.
    What do i don't understand in socket instatiation or class creation?
    is there someting related to stack/heap creation or someting?
    i also tried to instatiate like this:

    streamerSlot *clientSat1=new streamerSlot(1238,"SAT1-SNTL");
    

    but it is the same, the tcp connection seems to collapse.
    Or maybe with the parent/child mecanism? i don't understand theses mecanisms, so hope someone is far more illuminated than me....

    Regards.
    B.HAHN

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      Any chances you have a second call to the test function somewhere else in your code ?

      On an unrelated note, since you are using using Qt, you don't need to use raw char array especially since connecToHost uses a QString for the hostname.
      And second unrelated note, usually, class names in C++ are UpperCamelCase. This makes it easier to differentiate them from variable names.

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

      B 1 Reply Last reply
      0
      • SGaistS SGaist

        Hi and welcome to devnet,

        Any chances you have a second call to the test function somewhere else in your code ?

        On an unrelated note, since you are using using Qt, you don't need to use raw char array especially since connecToHost uses a QString for the hostname.
        And second unrelated note, usually, class names in C++ are UpperCamelCase. This makes it easier to differentiate them from variable names.

        B Offline
        B Offline
        beHa
        wrote on last edited by
        #3

        @SGaist Hello, thank you for your remarks. yes totally agree with char arrays...just lasy because i come from C world.
        anyway . no, the test function is not call anaywhere again. I really don't understand why instantiation fail,
        i tried to make test with my 4 cameras server at runtime. and if i create 4 different classes with same methods but wih one instantation , such as:

        StreamerSlot clientSat1(1238,"SAT1-SNTL");
        StreamerSlot2 clientSat2(1234,"SAT2-SNTL");
        StreamerSlot3 clientSat3(1236,"SAT3-SNTL");
        StreamerSlot4 clientSat4(1232,"SAT4-SNTL");
        
        

        i can see my streams.... too silly!!
        A notion that i totally don't understand for now is parent too child relationship.is there any clue that instantiation of QTcpSocket fail beacause my relation is not good?
        I'm too far from understanding this kind of problems now.

        Regards.

        1 Reply Last reply
        0
        • B Offline
          B Offline
          beHa
          wrote on last edited by
          #4

          Hello, i'm doubting too myself. and what about the classes variables?
          when i use them, don't i need to call such as:

          this->m_Image = QImage(1280,720, QImage::Format_RGB888);//RGB32);
          
          

          because for now, i use them such as:

          m_Image = QImage(1280,720, QImage::Format_RGB888);//RGB32);
          

          maybe the instantiation doesn't agree with this?
          hope this help to help me :)
          BH

          1 Reply Last reply
          0
          • B Offline
            B Offline
            beHa
            wrote on last edited by
            #5

            Hello all, i'm still on my issue...
            after searching,
            the program runn well since the second object creation.
            when there is only one object running, the readyread() slot is performing well,
            here you are the readyread slot:

            void streamerSlot::readyRead()
            {
              QByteArray      data;
              static qint64 imageSize = 0;
              QString currentSatName="";
              QByteArray currentSatData;
            
            //depart de trame , on recoit la taille, le nom du sat et les data params(SNTL)
                  if ( 0 == imageSize ) {
                      if (  socket->bytesAvailable() < (int)sizeof(qint64) ) {qDebug()<<"<";return;}
                      in >> imageSize;
                      in>>currentSatName;
                      in>>currentSatData;
            
                   //   qDebug()<<"reading.."<<n<<" " << imageSize<<"  "<<currentSatName<<"  "<<currentSatData;
            
                  }
            //si on a pas encore la taille necessaire on quitte
                  if (  socket->bytesAvailable() <  imageSize ) {qDebug()<<"s/i"<<socket->bytesAvailable()<<" "<<  imageSize;return;}
            //une fois qu'on l'a, on charge
                 in>>data;
            // et on traite Vers cv::Mat:
                  std::vector<uchar> vData(data.begin(), data.end());
                  cv::Mat matImg;
                  if(imageSize!=-1&&imageSize!=0)//&&data.size()>0)
                  {qDebug()<<"tcp "<<imageSize;
            
                  /*  commentedout for debuging matImg = cv::imdecode(cv::Mat(1,imageSize,CV_8UC1,&vData[0]), cv:: IMREAD_COLOR);
                    QImage image= Mat2QImage(matImg);
                    emit  newImage(image);
                   socket->flush();*/
                  }
            //Si on a un soucis eventuel, on vide tout
                 else
                  {
                    qDebug()<<"matrice a -1 "<<this<< " :erreur decodage tcp "<<imageSize;
                    QImage image = QImage(640,480, QImage::Format_RGB888);
                    image.fill(QColor("red"));
                    socket->flush();
                  }
                  imageSize = 0;
            }
            

            which is giving this print:
            data are growing in Qdatastream and when i have correct size of image, i go further:
            tcp 48737
            s/i 37416 48728
            s/i 48712 48728
            s/i 48712 48728
            tcp 48728
            s/i 37416 48602
            s/i 48586 48602
            s/i 48586 48602
            tcp 48602
            the QDatastream works ok, data are coming all is fine.
            after this the second opbject is created, and now, the readyRead slots are still running but data arriving are not good,
            the socket are still opened but data are now
            s/i 3751036 64622077935624
            s/i 3751036 64622077935624
            s/i 3759482 64622077935624
            s/i 1670978 64622077935624
            s/i 1695458 64622077935624
            s/i 1701170 64622077935624

            So my guess is that my class is not correctly written, maybe my variables are not instantiated corectly?

            i tried to add a descriptor id in the prints as this:

            qDebug()<<"s/i"<<socket->socketDescriptor()<<" "<<socket->bytesAvailable()<<" "<<  imageSize;return;
            

            s/i 1028 1882900 140630114172936
            s/i 1196 1254619 140630114172936
            s/i 1196 1284736 140630114172936
            s/i 1196 1284736 140630114172936
            s/i 1028 1895860 140630114172936
            s/i 1028 1895860 140630114172936
            s/i 1028 1907380 140630114172936
            s/i 1028 1930517 140630114172936
            s/i 1028 1930517 140630114172936

            we can see that the two sockets are running, they both exist. but data in datastream are crasy.
            So , i don't know where to seek now.
            many thanks!

            1 Reply Last reply
            0
            • B Offline
              B Offline
              beHa
              wrote on last edited by
              #6

              Hello all, seems that i'm i alone in the dark here, since, exept one tag from Sgaist helping me, nothing happened.
              anyway, seems that i finded the error.
              in my readyread slot, i create the imageSize variable in static....

              void streamerSlot2::readyRead()
              {
              //  QImage image;
                QByteArray      data;
                static qint64 imageSize = 0;
                QString currentSatName="";
                QByteArray currentSatData;
              ...
              

              so, with one object it is okay, the imageSize is created, fixed to zero and readyread runs....but with a second object instantiated...
              it is not the same, the variable is doing something i'm not understanding. but it lay to bad results.
              declared it in .h private section not in static. and my 2 instances are working now!!

              class streamerSlot : public QTcpSocket//QObject
              {
                  Q_OBJECT
              public:
                  explicit streamerSlot(int port,char *satName,QObject *parent = nullptr);
                  void test();
              signals:
                   void newImage(const QImage &);
              public slots:
                  void connected();
                  void disconnected();
                  void bytesWritten (qint64 bytes);
                  void readyRead();
              
              private:
                  QTcpSocket *socket;
                  QImage m_Image;
                  char m_satName[16];
                  int m_satPort=0;
                  QImage Mat2QImage(cv::Mat const& src);
                  cv::Mat QImage2Mat(QImage const& src);
              QDataStream in;
              qint64 imageSize = 0;
                    char _datout=0;
                    int n=0;
              };
              

              need to make some more test tomorrow with my 4 units to be sure, but...smells good!

              Regards.

              JonBJ 1 Reply Last reply
              0
              • B beHa

                Hello all, seems that i'm i alone in the dark here, since, exept one tag from Sgaist helping me, nothing happened.
                anyway, seems that i finded the error.
                in my readyread slot, i create the imageSize variable in static....

                void streamerSlot2::readyRead()
                {
                //  QImage image;
                  QByteArray      data;
                  static qint64 imageSize = 0;
                  QString currentSatName="";
                  QByteArray currentSatData;
                ...
                

                so, with one object it is okay, the imageSize is created, fixed to zero and readyread runs....but with a second object instantiated...
                it is not the same, the variable is doing something i'm not understanding. but it lay to bad results.
                declared it in .h private section not in static. and my 2 instances are working now!!

                class streamerSlot : public QTcpSocket//QObject
                {
                    Q_OBJECT
                public:
                    explicit streamerSlot(int port,char *satName,QObject *parent = nullptr);
                    void test();
                signals:
                     void newImage(const QImage &);
                public slots:
                    void connected();
                    void disconnected();
                    void bytesWritten (qint64 bytes);
                    void readyRead();
                
                private:
                    QTcpSocket *socket;
                    QImage m_Image;
                    char m_satName[16];
                    int m_satPort=0;
                    QImage Mat2QImage(cv::Mat const& src);
                    cv::Mat QImage2Mat(QImage const& src);
                QDataStream in;
                qint64 imageSize = 0;
                      char _datout=0;
                      int n=0;
                };
                

                need to make some more test tomorrow with my 4 units to be sure, but...smells good!

                Regards.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #7

                @beHa said in QtcpSocket instantiation not morking properly:

                declared it in .h private section not in static. and my 2 instances are working now!!

                Indeed! When you declare a variable static in (say) streamerSlot2::readyRead() that means there is only one (shared) instance of the variable used no matter how many different instances of streamerSlot2 you access it from. This is (usually) a very bad idea. Basically keep clear of static unless you really know what you are doing.

                When you move it to a member variable of streamerSlot2 you have separate imageSises for each instance of streamerSlot2. Which is what you want here!

                1 Reply Last reply
                2
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Damn ! I was looking for a static variable but missed the only one that was there.

                  When handling video stream image sizes, it's always a bad idea to do that through a static variable. Static variables create hidden shared global states when used like that.

                  @beHa said in QtcpSocket instantiation not morking properly:

                  Hello all, seems that i'm i alone in the dark here, since, exept one tag from Sgaist helping me, nothing happened.

                  No you're not. It's just that you asked your question on the weekend on a voluntary driven forum, hence a bit less active :-)

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

                  1 Reply Last reply
                  0
                  • B Offline
                    B Offline
                    beHa
                    wrote on last edited by
                    #9

                    HEllo All
                    YEs, just kidding, i know i always can't wait.
                    So yes, i close and solve this topic.
                    Should be a topic itself
                    Regards!
                    B.HAHN

                    1 Reply Last reply
                    0

                    • Login

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