QTcpSocket przekazanie do watku danych z głownego okna aplikacji

0

Watek łączy sie z hostem i czeka na dane za pomocą "QTcpSocket::readyRead"
Chciałbym teraz z głównego okna aplikacji wysłać przez istniejące QTcpSocket

Zrobiłem metodę
ConnectTCP::write_data(...)

Metoda write_data() uruchamia sygnał
signal_write_data(...)

Sygnał signal_write_data łacze ze slotem :

    void slot_write_data(DATA_stream &mem)
    {
     socket->write((char*)mem.data(),mem.size()*sizeof(mem[0]));
   }

w kodzie sa trzy wersje [1] [2] i [3]
I działa tylko wersja z LAMBDA , dlaczego ?

typedef std::vector<uint8_t> DATA_stream;

class ConnectTCP : public QThread
{
    Q_OBJECT
private:
    QTcpSocket* socket;    
private slots:
    void slot_write_data(DATA_stream &mem)
    {
     socket->write((char*)mem.data(),mem.size()*sizeof(mem[0]));
   }
     
signals:
    void signal_write_data(DATA_stream &mem);

public:
    void write_data(DATA_stream &mem){
        emit signal_write_data(mem) ;
    }
private:
    void run()
    {
        QEventLoop eventLoop;
        socket = new QTcpSocket(&eventLoop);
        socket->connectToHost(QHostAddress("127.0.0.1"), 6001);

        // enqueue or process the data
        QObject::connect(socket, &QTcpSocket::readyRead, &eventLoop, [socket]
        {
          // to działa nie istotne dla problemu 
           QByteArray datas = socket->readAll();
        }


        //  [1] TO NIE DZIAŁA !!! nawet nie uruchamia sie slot_write_data
        //QObject::connect(this, SIGNAL(signal_write_data(&DATA_stream)), this, SLOT(slot_write_data(&DATA_stream)));        

        // [2]  TO TEZ NIE DZIALA !!! uruchamia sie slot_write_data ale danie się nie wpisują do SOCKET 
        //QObject::connect(this, &ConnectTCP::signal_write_data, this, &ConnectTCP::slot_write_data);


        // [3] A TO DZIAŁA !!!
        QObject::connect(this, &ConnectTCP::signal_write_data, this, [socket](DATA_stream &mem) {
            printf("CALL: slot_write_data\n");
            
            if(socket->state() != QAbstractSocket::ConnectedState  )
            {
                printf("!!!! ConnectTCP not connected !!!!\n");
                return;
            }

            if(mem.size()>0)
            {
                //qDebug()<<socket->state();
                qint64 result =  socket->write((char*)mem.data(),mem.size()*sizeof(mem[0]));
                socket->flush();
                qDebug()<<"RESULT="<< result;
            }
      }// end LAMBDA  ConnectTCP::signal_write_data
        
   

      // Quit the loop (and thread) if the socket it disconnected. You could also try reconnecting
      QObject::connect(socket, &QTcpSocket::disconnected, &eventLoop, [&eventLoop]
      {
          eventLoop.quit();
      });
    
      eventLoop.exec();
    
      delete socket;   
    }//end run()      
}//end class
1
  1. to zupełnie niepoprawny sposób łączenia, poczytaj dokumentację jak się używa connect() z nazwą. Albo i nie, bo teraz to praktycznie wcale nie powinno być używane
  2. powinno "działać"
  3. również

powtarzałem to już wielokrotnie, powtórzę jeszcze raz: niepotrzebnie bawisz się w wątki i utrudniasz sobie i wszystkim dookoła życie. Założę się, że problemem jest czas życia zmiennej, którą przekazujesz do wątku przez referencję, i masz zwyczajnie UB

0

Bez watków mam już wersję ale jest drobny problem bo źródło danych (mój serwer) to prosty system embedded, tak proste że jest w stanie wysyłać tylko prosty strumień danych (bez opcji na sensowny protokół komunikacyjny), urzadzenie ma tak małe FIFO że jak czegoś nie odbiorę to mam utratę danych wiec tylko dlatego QTcpSocket jest w oddzielnym watku. Aby nic nie zakłócało transmisji.

1

https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong
vs
https://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html (daje tylko po to, że trafiają się tacy co się nie zgadzają, ale źródło jest zdecydowanie mniej godne zaufania i jest mniej rzeczowe).

0
Adamek Adam napisał(a):
        //  [1] TO NIE DZIAŁA !!! nawet nie uruchamia sie slot_write_data
        //QObject::connect(this, SIGNAL(signal_write_data(&DATA_stream)), this, SLOT(slot_write_data(&DATA_stream)));

A niby czemu ma to działać, skoro tu jest literówka (zła kolejność).
Taka wada starego stylu łączenia sygnałów i slotów, że błędy wykrywa w runtime.

0

Poprawki jakie trzeba nanieść:

  • rzeczywiście referencja to nie najmądrzejsze
  • brak qRegisterMetaType< DATA_stream >(); oraz Q_DECLARE_METATYPE(DATA_stream)
  • sygnały muszą być skierowane do &eventLoop (this jako target jest błędem , bo wtedy slot jest poza wątkiem w którym jest QTcpSocket )

Watki to zło konieczne.

2
Adamek Adam napisał(a):

Watki to zło konieczne.

Z mojej obserwacji wynika, że 90% ludzie wpychają watki tam, gdzie nie są one potrzebne.

1 użytkowników online, w tym zalogowanych: 0, gości: 1