How to write data to TcpSocket from another thread?
-
On the computer work two thread. First, the Tcp server transfers data from the target PC to the UART. The second one checks the buffer for data (polling). UART is very slow so it is impossible to run everything in one thread. Need send data via Tcp Server to the target PC upon arrival of the data to UART, but when calling the write method to the port, the server drops to the records ( socket->write ( data ); ) or even so does not allow writing to the port ( socket->write ( "data" ); ). Where can I find documentation or an example to resolve this issue?
UART the error happens after calling in the parse method of recording myserver.write():
void UART_Protokol::ParseCommand() { MyServer myserver; if(sp_dataString == "Start") { TransmitData = "ready"; sp_Send(TransmitData); qDebug()<<"Self-test"; } if(sp_dataString == "ready") qDebug()<<"Self-test"; if (sp_dataString =="MG1") myserver.write("MG1"); //After the Debug message is displayed, the application crashes if (sp_dataString =="MG0") myserver.write("MG0"); if (sp_dataString =="MG") qDebug()<<"Calibration..."; }
Part of the Tcp server here is the method of writing MyServer::write at the very end:
#include "myserver.h" MyServer::MyServer(){} MyServer::~MyServer(){} void MyServer::startserver() { if (this->listen(QHostAddress::Any,8981))qDebug()<<"Server started"; else{ qDebug()<<"Error started server";} } void MyServer::incomingConnection(int socketDescriptor ) { socket = new QTcpSocket(this); socket->setSocketDescriptor( socketDescriptor); connect(socket,SIGNAL(readyRead()),this,SLOT(read())); connect(socket,SIGNAL(disconnected()),this,SLOT(disconect())); qDebug()<<socketDescriptor<<"Client connected"; socket->write("Connection"); } void MyServer::read() { UART_Protokol UART; UART.StartProtokol( false ); arr = socket->readAll(); data += arr; if ( data == "wu" )UART.sp_Send("wu"); if ( data == "su" )UART.sp_Send("su"); if ( data == "au" )UART.sp_Send("au"); if ( data == "du" )UART.sp_Send("du"); if ( data == "qu" )UART.sp_Send("qu"); if ( data == "eu" )UART.sp_Send("eu"); if ( data == "wd" )UART.sp_Send("wd"); if ( data == "sd" )UART.sp_Send("sd"); if ( data == "ad" )UART.sp_Send("ad"); if ( data == "dd" )UART.sp_Send("dd"); if ( data == "qd" )UART.sp_Send("qd"); if ( data == "ed" )UART.sp_Send("ed"); if (data == "SD1")UART.sp_Send("SD1"); if (data == "SD0")UART.sp_Send("SD0"); if (data == "cl")UART.sp_Send("cl"); if( arr[0] == Mask[0]&& arr[1] == Mask[1]) { int length = 0; QByteArray dt = "tr"; trust[0] =0; trust[1] =0; trust[2] =0; length = arr[2]; trust[0] =arr[3]; trust[1] =arr[4]; trust[2] =arr[5]; truster = convert(trust, length - 48); dt[2] = truster; UART.sp_Send_integer(dt); } arr.clear(); data = ""; } void MyServer::disconect() { socket->deleteLater(); } void MyServer::write (QByteArray dat) { //An error occurs here qDebug()<<dat; // Debug work is fine socket->write(dat); // it doesn't work too socket->write ("MG1"); }
Just in case UART and TcpServer threads are started:
#include <QCoreApplication> #include <myserver.h> #include <protokol_obmena_cherez_uart.h> #include <QDebug> #include <thread> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); UART_Protokol Serial; Serial.StartProtokol( false ); std::thread serial (&UART_Protokol::Event, Serial); MyServer Server; Server.startserver(); return a.exec(); }
-
Hi
Could you not just use signal and slot ?
So when UART has data it emit signal to MyServer to actually send some reply ?
But im having hard time to understand the code as you seem to both
make a UART_Protokol and Myserver in main but at the same time
also make new one in void MyServer::read() and
a server in void UART_Protokol::ParseCommand()
so im not really sure what class should be talking to what class. -
I've tried using the signal for the recording method but nothing either fail.
It was necessary to create a new class to inherit Q_OBJECT otherwise the linker does not allow to use WiringPi for work with UART.
class Signals: public QObject { Q_OBJECT public: Signals(); public slots: void setValue(); signals: void event_uart(); };
Signals::Signals(){} void Signals::setValue() { emit event_uart(); }
The MyServer::write slot does not work when sending a signal.
void MyServer::incomingConnection(int socketDescriptor ) { socket = new QTcpSocket(this); Signals ref; socket->setSocketDescriptor( socketDescriptor ); connect(socket,SIGNAL(readyRead()),this,SLOT(read())); connect(socket,SIGNAL(disconnected()),this,SLOT(disconect())); connect(&ref,SIGNAL(event_uart()), this,SLOT(write())); //connected signal with UART qDebug()<<socketDescriptor<<"Client connected"; socket->write("Connection"); }
void UART_Protokol::ParseCommand() { Signals ref; if(sp_dataString == "Start") { TransmitData = "ready"; sp_Send(TransmitData); qDebug()<<"Self-test"; } if(sp_dataString == "ready") qDebug()<<"Self-test"; if (sp_dataString =="MG1") { qDebug()<<"Start calibration..."; ref.setValue(); // send signal } if (sp_dataString =="MG0") { qDebug()<<"End calibration..."; ref.setValue(); } if (sp_dataString =="MG") { qDebug()<<"Calibration..."; } }
-
Hi
I wonder aboutvoid MyServer::incomingConnection(int socketDescriptor ) { socket = new QTcpSocket(this); Signals ref; // this is local object and will be deleted as soon as function ends socket->setSocketDescriptor( socketDescriptor ); connect(socket,SIGNAL(readyRead()),this,SLOT(read())); connect(socket,SIGNAL(disconnected()),this,SLOT(disconect())); connect(&ref,SIGNAL(event_uart()), this,SLOT(write())); //connected signal with UART qDebug()<<socketDescriptor<<"Client connected"; socket->write("Connection"); }
Since Signals ref; is gone as soon as function ends, how will it ever emit event_uart()
once data arrives ?i was expecting something like
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); UART_Protokol Serial; Serial.StartProtokol( false ); std::thread serial (&UART_Protokol::Event, Serial); MyServer Server; connect(&Serial, UART_Protokol::ServerWrite, &Server, MyServer::write, Qt::QueuedConnection); // or similar Server.startserver(); return a.exec(); } and then in (and other places ) void UART_Protokol::ParseCommand() { // MyServer myserver; // why make a new local server when you have one in main ?? ..... if (sp_dataString =="MG1") emit ServerWrite("MG1"); //emit signal to server in main ..... }
-
I can't use the emit ServerWrite signal because I need UART_Protokol class inherit to the QObject class without this will be error when creating the signal slot. But i cannot inherit this class because the linker throws an error.
class UART_Protokol { Q_OBJECT //If i inherit QObject to the UART_Protokol: undefined reference to `vtable for UART_Protokol' //And without Q_OBJECT I can't use signals signals: void ServerWrite (QByteArray dat);
Is this how it's gonna work? Can I use a signal from another class?
QObject::connect (&signal,&Signals::setValue, &Server,&MyServer::write, Qt::QueuedConnection);
-
HI
Cant you just do
class UART_Protokol : public QObject
{
Q_OBJECT
...ah,
undefined reference to `vtable for UART_Protokol'thats happens often.
just inherit from QObject
then clean all of build folder
and then rebuild all.
Its a known error coming from not all is recompiled after adding QObject -
I cleaned up the entire contents of the folder and reassembled everything. Error appeared: "Class contains Q_OBJECT macro but does not inherit from QObject ":
/#ifndef PROTOKOL_OBMENA_CHEREZ_UART_H #define PROTOKOL_OBMENA_CHEREZ_UART_H #include <QString> #include <thread> #include <myserver.h> #include <QObject> class UART_Protokol { Q_OBJECT
If inherit a class from QObject how in other example, other errors occur:
#ifndef PROTOKOL_OBMENA_CHEREZ_UART_H #define PROTOKOL_OBMENA_CHEREZ_UART_H #include <QString> #include <thread> #include <myserver.h> #include <QObject> class UART_Protokol : public QObject { Q_OBJECT
use of deleted function ‘UART_Protokol::UART_Protokol(const UART_Protokol&)’
: _M_head_impl(std::forward<_UHead>(__h)) { }‘QObject::QObject(const QObject&)’ is private within this context
use of deleted function ‘QObject::QObject(const QObject&)’
class UART_Protokol : public QObject
^~~~~~~~~~~~~
^
no matching function for call to ‘std::tuple<std::_Mem_fn<void (UART_Protokol::)()>, UART_Protokol>::tuple(std::_Mem_fn<void (UART_Protokol::)()>, UART_Protokol&)’
: _M_bound(std::forward<_Tp>(__f), std::forward<_Up>(__args)...)
^ -
If I inherit the class :
class UART_Protokol : public QObject { Q_OBJECT
and comment on a thread, everything is going without errors:
// std::thread serial (&UART_Protokol::Event, Serial); // serial.detach();
even connecting signal to slot, build is fine:
QObject::connect (&Serial,&UART_Protokol::ServerWrite, &Server,&MyServer::write, Qt::QueuedConnection);
That's just it I need to check the UART buffer for reading messages.
-
Did you read the document I linked regarding copying QObject based classes ?