PDA

View Full Version : problem with Tcp socket reception in a thread...



medampudi
9th September 2010, 21:38
Hello every one,

I am really grateful for such a wonderful support forum for QT. I could get most of my question answered till today except this one... Great going...

the basic functionality:
create a gui application and then create a thread that holds a tcpsocket connection and perform a tedious calculation on the data received on the Socket..

the tcp connection at which the data is received is LocalHost:3000


I created a basic QT GUI application and then at the press of a button; i would create a thread with the command...


mythread *txt = new mythread();
txt->start();


the thread is defined with the following constructor...
mythread.h



class mythread : public QThread
{
Q_OBJECT
public:
mythread(QObject *parent = 0);
void run();
private :
QTcpSocket socket;
}



mythread.cpp




mythread::mythread(QObject *parent)
: QThread(parent)
{
}

void mythread::run(){

qint64 maxlen = 128;
socket.connectToHost(QHostAddress::LocalHost,3000) ;
if (socket.waitForConnected(1000))
qDebug("Connected!");
char buffer[128];
//QDataStream in(&socket);
//in.setVersion(QDataStream::Qt_4_6);
while(1){
qint64 len = socket.readLine(buffer, maxlen);

if(len < 0){
qDebug()<<"the break function";
break;
}
qDebug()<<"The buffer is" <<buffer<<"and its size is "<<len;
}
}



After i run this, i always get the error saying that




QObject: Cannot create children for a parent that is in a different thread. (Parent is QTcpSocket(0x980df60), parent's thread is QThread(0x3d4ec8), current thread is mythread(0x980df58)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x980df60), parent's thread is QThread(0x3d4ec8), current thread is mythread(0x980df58)
Connected!
The buffer is and its size is 0
The buffer is and its size is 0
The buffer is and its size is 0
The buffer is and its size is 0
The buffer is and its size is 0
The buffer is and its size is 0
The buffer is and its size is 0
The buffer is and its size is 0
The buffer is and its size is 0
The buffer is and its size is 0




Could any one help me in this regard...

Thanking you

Rajesh Medampudi....

wysota
9th September 2010, 21:48
In general the problem is mythread object lives in the context of the main thread and not the thread it represents. So your socket object will be created in the context of the main thread and you should handle it there. I think that in your case everything you have to do is to get rid of the socket member variable and create the socket instance in the run() method.


void mythread::run() {
QTcpSocket socket;
qint64 maxlen = 128;
socket.connectToHost(QHostAddress::LocalHost,3000) ;
if (socket.waitForConnected(1000))
qDebug("Connected!");
else { ... }
char buffer[128];

while(1){
// you should wait for data here!
socket.waitForReadyRead();
// and make sure there is a whole line to read!
if(!socket.canReadLine()) continue;
qint64 len = socket.readLine(buffer, maxlen);
if(len < 0){
qDebug()<<"the break function";
break;
}
qDebug()<<"The buffer is" <<buffer<<"and its size is "<<len;
}
}
I also corrected your code a bit but I don't guarantee it will work.

squidge
9th September 2010, 21:51
Why use TCP socket reception in a thread? Do it in your main UI threead, and then spawn off the tedious calculation into a seperate thread and use signals to signify the finish of the calculation (or use QtConcurrent or similar).

medampudi
9th September 2010, 22:59
thank you very much @wysota - the program works like a charm... might be that i needed some commands to wait and accept the TCP values.Thank you very much... Any how My first foray into Threads and TCP works now...

@squidge.. The program needs to use the same thread and store teh values of past variables too and using a concurrent programming did not meet my needs of having a threaded simple interface.. And i think you are right that i could just call this from the main UI and hence eliminate the intermediate Thread but the problem being portability and no. of changes in the original source code of the Tedious Function...(It inherits a lot of other custom defined base classes that are not native QT kind) hence to reduce my work, I just used a Thread to work it out all together.. the thread uses the signals and slots along with the main UI class for signaling events.

I also wanted to use this experience of threads as a learning ground for the other part of the application of communicating with the robots...

Thank you Once Again Both of you.... for your inputs on this program...

Drauggul
14th February 2013, 14:57
Hi! I have quite similar problem with Qthread.

Everything is ok until I unlink the Ethernet cable. And Try reconnect when connection error signel recived.


from console:


socket: QObject(0x0)
socket: QTcpSocket(0xafb02498)
Connecting to: "192.168.1.5"
resize event
"Ppm2_window" OGOLNY
show event
MODEL:x: false
"Ppm2_window" OGOLNY
console request
permision to send data: true
Socket state: QAbstractSocket::HostLookupState
Socket state: QAbstractSocket::ConnectingState
Not connected: true
sock open: false
Socket state: QAbstractSocket::UnconnectedState
sock open: false
Socket error: "Unknown error"
Socket error: QAbstractSocket::SocketTimeoutError

Connecting to: "192.168.1.5"
Socket state: QAbstractSocket::HostLookupState
Socket state: QAbstractSocket::ConnectingState
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0xafb02498), parent's thread is TcpClient(0x8473da0), current thread is QThread(0x82f66a8)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0xafb02498), parent's thread is TcpClient(0x8473da0), current thread is QThread(0x82f66a8)
Socket state: QAbstractSocket::UnconnectedState
sock open: true
Socket error: "Host unreachable"
Socket error: QAbstractSocket::NetworkError
Network error: "Host unreachable"
Not connected: true
sock open: false
Socket state: QAbstractSocket::UnconnectedState
sock open: false


My Qestion is. Why it works like that? I have no idea how to solve this problem



#ifndef TCPCLIENT_H
#define TCPCLIENT_H

#include <QThread>
#include <QTcpSocket>
#include <QAbstractSocket>
#include <QObject>
#include <QDebug>
#include <QTime>
#include "globalne.h"

class TcpClient : public QThread
{
Q_OBJECT



public:

explicit TcpClient(QObject *parent = 0);
~TcpClient();
void run();
bool StartConnection();
void zakoncz_polaczenie_z_e1000();

signals:
void dataReady(QByteArray, QTime);
void connectionError();

public slots:
void readyRead();
void disconnected();
void connected();
void stateChanged(QAbstractSocket::SocketState);
void displayError(QAbstractSocket::SocketError);
// void bytesWritten (qint64 bytes);


private:

// CanMon canmnon_parent;
// QTcpSocket socket;
QTcpSocket *socket;
QTime time;
// QStringList lista;
bool ponawiaj;



};

#endif // TCPCLIENT_H






//#include "tcpclient.h"

//TcpClient::TcpClient(QObject *parent) :
// QObject(parent)
//{
//}

#include <QStringList>
#include "tcpclient.h"

#include <QFile>
#include <QTextStream>


TcpClient::TcpClient(QObject *parent) :
QThread(parent)
{

socket = NULL;
qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
ponawiaj = true;

}

TcpClient::~TcpClient()
{
// qDebug() << "p";


disconnect(socket,SIGNAL(connected()), this, SLOT(connected()));
disconnect(socket,SIGNAL(readyRead()),this,SLOT(re adyRead()));
disconnect(socket,SIGNAL(disconnected()), this, SLOT(disconnected()));
// disconnect(socket,SIGNAL(stateChanged(QAbstractSoc ket::SocketState)),this,SLOT(stateChanged(qSockSta te)));
socket->close();
qDebug() << "socket open: " << socket->isOpen();
delete socket;
}

void TcpClient::stateChanged(QAbstractSocket::SocketSta te st)
{
qDebug() << "Socket state: " << st;
switch(st)
{
case QAbstractSocket::UnconnectedState:
qDebug() << "sock open: " << socket->isOpen();
break;
}
}

void TcpClient::displayError(QAbstractSocket::SocketErr or se)
{
qDebug() << "Socket error: " << socket->errorString();
qDebug() << "Socket error: " << se;

switch(se)
{
case QAbstractSocket::SocketTimeoutError:
StartConnection();
break;
case QAbstractSocket::NetworkError:
qDebug() << "Network error: " << socket->errorString();
break;

}

// this->StartConnection();
}

bool TcpClient::StartConnection()
{
#define z_pliku 0

#if z_pliku
QFile mFile("iphosta.cfg");
if (!mFile.open(QFile::ReadOnly | QFile::Text))
{
qDebug() << mFile.errorString();
qDebug() << "nie otworzono pliku... próba połączenia z localhost";
socket->connectToHost("localhost",4010);
}
else
{
QTextStream in(&mFile);
QString host = in.readAll();
mFile.close();
qDebug() << "Connecting to: " << host;
socket->connectToHost(host,4010);
}
#else
QString host = "192.168.1.5";
// QString host = "192.168.1.48";
qDebug() << "Connecting to: " << host;

socket->connectToHost(host,4010);
#endif

if(socket->waitForConnected(5000))
{
qDebug() << "Connected: " << socket->isOpen();

}
else
{
qDebug() << "Not connected: " << socket->isOpen();
socket->close();
}

qDebug() << "sock open: " << socket->isOpen();

return socket->isOpen();
}

void TcpClient::zakoncz_polaczenie_z_e1000()
{
int result;
if (socket->state())
{
result = socket->write(QByteArray::fromHex(QString("e1fc0000000000000000000000000000000000000000000000 0000f7e000e2").toAscii()));
qDebug() << "nadano koniec polaczenia: " << result;
this->msleep(500);
qDebug() << "minely 2 sekundy";
}
ponawiaj = false;
}

void TcpClient::run()
{
qDebug() << "socket: " << socket;
if(!socket)
socket = new QTcpSocket();
qDebug() << "socket: " << socket;

connect(socket,SIGNAL(connected()), this, SLOT(connected()));
connect(socket,SIGNAL(readyRead()),this,SLOT(ready Read()));
connect(socket,SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(displayError(QAbstractSocket::SocketError)));
connect(socket,SIGNAL( stateChanged(QAbstractSocket::SocketState)),this, SLOT(stateChanged(QAbstractSocket::SocketState)));
// error(QAbstractSocket::SocketError)
// SIGNAL(stateChanged(qSockState)),this,SLOT(tcState Changed(qSockState)));

this->StartConnection();
this->exec();

}

void TcpClient::connected()
{
qDebug() << "connection established: " << socket->isOpen();
}

void TcpClient::disconnected()
{
qDebug() << " Disconnected";
}

void TcpClient::readyRead()
{

QByteArray data;

// qDebug() << "Redy read ";

if (socket->bytesAvailable() > 0)
{
// qDebug() << "dostepne bajty: " << socket->bytesAvailable();

data = socket->readAll();
// qDebug() << "odebrano: " << data.toHex();
time.start();
// qDebug() << "TIME: " << time.toString() << "." << time.msec();
emit dataReady(data, time);
}
}

anda_skoa
15th February 2013, 04:17
That looks weird quite wrong. All your slots are being executed in the main thread (cross thread signal/slot connections, receiver object "thsi" belongs to main thread).

Cheers,
_