免责声明:我对 Qt 和任何围绕线程和网络的编程都比较陌生。我还采用了很多来自 Qt 示例、API 和其他在线示例的代码。
所有代码都可以在 GitHub 上找到。这段代码相对简单,因为它可以减去剥离 GUI。我认为以这种方式提供它也会有所帮助,而不是仅仅粘贴下面的代码。
我想使用并相信我需要使用线程,因为我需要多个客户端向服务器发送请求,服务器运行一些 SQL 代码,然后将结果吐回客户端(基本上派生一个 MySQL 服务器,但具体到什么我在做)。不过现在,我只是在努力学习这一切的运作方式。
话虽如此,正如标题所述。我的客户端可以连接到服务器,服务器设置线程,并将通过 readReady 接收数据(字符串)。读入数据后,现在我只是想将其回显给客户端。它会这样做,但只有一次。然后它吐出:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNativeSocketEngine(0x266cca92ea0), parent's thread is serverThread(0x266cca9ed60), current thread is QThread(0x266cac772e0)
除非我让客户端重新连接,否则我无法向服务器发送任何进一步的数据,然后在发送数据后,它将完成其工作,但随后会吐出相同的错误并停止运行。我尝试了很多不同的东西,但似乎无法解决问题。我什至尝试按照 API 中的建议为此设置一个 SIGNAL/SLOT:
重要的是要记住 QThread 实例存在于实例化它的旧线程中,而不是调用 run() 的新线程中。这意味着 QThread 的所有排队槽都将在旧线程中执行。因此,希望在新线程中调用槽的开发人员必须使用工作对象方法;不应将新插槽直接实现到子类 QThread 中。
无论如何,任何帮助将不胜感激!我的代码如下..
服务器
服务器线程.cpp
// Project
#include "ServerDialog.h"
#include "ServerThread.h"
ServerThread::ServerThread(qintptr _socketDiscriptor, QObject *parent /*= 0*/)
: QThread(parent)
{
socketDiscriptor = _socketDiscriptor;
}
void ServerThread::run()
{
emit threadStarted(socketDiscriptor);
// Start Thread
clientSocket = new QTcpSocket;
// Set SocketDisc
if (!clientSocket->setSocketDescriptor(socketDiscriptor))
{
emit error(clientSocket->error());
return;
}
// Connect Socket and Signal
connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readyRead()));
connect(clientSocket, SIGNAL(disconnected()), this, SLOT(disconnected()));
//// Loop Thread to Stay Alive for Signals and Slots
exec();
}
void ServerThread::readyRead()
{
QDataStream in(clientSocket);
in.setVersion(QDataStream::Qt_5_7);
in.startTransaction();
QString dataReceived;
in >> dataReceived;
if (!in.commitTransaction())
{
emit readyReadError(socketDiscriptor);
return;
}
emit readyReadMessage(socketDiscriptor, dataReceived);
echoData(dataReceived);
}
void ServerThread::disconnected()
{
emit threadStopped(socketDiscriptor);
clientSocket->disconnect();
clientSocket->deleteLater();
this->exit(0);
}
void ServerThread::echoData(QString &data)
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_7);
out << data;
clientSocket->write(block);
}
因此,ServerThread.cpp
在调用 echoData 时,即出现错误并且 Socket 停止运行。
任何和所有的帮助将不胜感激。我知道还有一些关于线程的“不能为...创建孩子”的其他帖子。但我没有发现其中任何一个有帮助。我确实觉得有趣但不理解的一件事可能是使用 moveToThread() 但对此有很多不同的评论。
我最好通过代码示例和解释来学习,而不是仅仅通过解释或指向 API 的指针。谢谢!