对于一个QTcpServer服务器来说,每当有新客户端连接时,系统会为其分配一个新的QTcpSocket对象进行管理。默认情况下,在incomingConnection函数中创建的QTcpSocket对象将在应用程序主线程中运行,而不是连接所需的处理线程中运行。如果开发者需要确保收到数据的顺序以及避免线程竞争,可以采取以下方式:
1. 将QTcpSocket的派生类(如MyTcpSocket)定义为私有,并提供一个公共的工厂函数 createNewSocket(),在其中设置信号槽并调用QObject::moveToThread(QThread *targetThread)函数将该socket放进指定的线程处理。
void MyThread::incomingConnection(qintptr socketDescriptor) { MyTcpSocket* socket = MyTcpSocket::createNewSocket(); // 手动断开Qt::AutoConnection机制,信号与动作都在父线程内循环 QObject::disconnect(socket, 0, 0, 0); connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater())); connect(this, SIGNAL(stop()), socket, SLOT(slotStop())); connect(socket, SIGNAL(signalSendData(const QByteArray&)), this, SLOT(slotRecvData(const QByteArray&))); socket->setSocketDescriptor(socketDescriptor); socket->moveToThread(m_thread); // 放进目标线程 }
2.在createNewSocket()函数内部实例化MyTcpSocket对象,在构造函数中设置this->moveToThread(thread)方法,把MyTcpSocket的运行线程设置为指定处理线程。
MyTcpSocket* MyTcpSocket::createNewSocket() { MyTcpSocket *socket = new MyTcpSocket(); socket->moveToThread(targetThread); return socket; } MyTcpSocket::MyTcpSocket(QObject *parent) : QTcpSocket(parent) { connect(this, SIGNAL(readyRead()), this, SLOT(readData())); connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError))); connect(this, &QTcpSocket::disconnected, this, &QTcpSocket::deleteLater); }
使用这种方法,可以确保处理m_thread线程的操作发生在MyTcpSocket对象所绑定的线程上,避免了许多线程安全问题和不确定性。
标签:SLOT,socket,MyTcpSocket,线程,connect,QTcpSocket,Socket,Qt From: https://www.cnblogs.com/david-china/p/17365699.html