Writing data to a TcpSocket in own Thread

2019-02-11 01:13发布

问题:

I got a problem with my threaded TCP-Server.
I can open my Server, a new Socket is created an I can receive data over the socket (I used the readyRead() signal and then used readLine() to read, which is working fine. Now I want to write data to this Socket from another Thread so I created a public slot writeData() which should take care of this. I connected the writeData() slot with QueuedConnection (also tried AutoConnection) but all I get when I call the m_socket->write() is an error message:

QObject: Cannot create children for a parent that is in a different thread. (Parent is QNativeSocketEngine(0x12f0f70), parent's thread is ServerThread(0xfbbae8), current thread is QThread(0xfa7c48)

Just a minimal example here:
I omitted the connect from my other Thread to the writeData() slot because I think everyone can imagine that ;)

class Server : public QTcpServer {
  Server();
protected:
  void incomingConnection(int socketDesc);
}

Server::Server() : QTcpServer() {
  this->listen(QHostAddress::Any, PORT);
}

void Server::incomingConnection(int socketDescriptor) {
  ServerThread *t = new ServerThread(socketDescriptor);
  t->start();
}

class ServerThread : public QThread {
  ServerThread(int socketDescriptor);
protected:
  void run();
public slots:
  void writeData(QString data);
private:
  int m_socketDescriptor;
  QTcpSocket *m_socket;
}

ServerThread::ServerThread(int socketDescriptor) : QThread(), m_socketDescriptor(socketDescriptor) {}

void ServerThread::run() {
  m_socket = new QTcpSocket();
  m_socket->setSocketDescriptor(m_socketDescriptor);
  exec();
}

void ServerThread::writeData(QString data) {
  m_socket->write(data.toAscii());
}

Thanks in advance.

回答1:

Your error message means:

Your signal-slot communication happens on ServerThread instance which was created and belongs to main thread. However instance of ServerThread member m_socket was created and belongs to other thread.

I would suggest you to create simple QThread and move your object into it.

void Server::incomingConnection(int socketDescriptor) {
  QThread *t = new QThread();
  ClientConnection *client = new ClientConnection(socketDescriptor);
  client->moveToThread(t);

  // go
  t->start();
}

class ClientConnection : public QObject {
Q_OBJECT
public:
  ClientConnection(int socketDescriptor, QObject *parent = 0);
public slots:
  void writeData(QString data);
private:
  int m_socketDescriptor;
  QTcpSocket *m_socket;
}