QTcpSocket and Multi-thread
-
Hi guys!
Dose the following code is correct or safe?struct TcpSocketQPDeleter { static inline void cleanup(QTcpSocket* pTcpSocket) { if(Q_NULLPTR!=pTcpSocket) { if(pTcpSocket->isOpen()) { pTcpSocket->close(); delete pTcpSocket; } } } }; class TestTcp: public QObject { Q_OBJECT public: TestTcp(); ~TestTcp()override =default; void init(QString ip, int port); public: bool testStart(QString ); public: signals: void has_received(); private: void readData(); QScopedPointer<QTcpSocket,QPUNDetails::TcpSocketQPDeleter> m_tcpClient{nullptr}; }; TestTcp::TestTcp() { this->init(); } void TestTcp::init(QString ip, int port) { m_tcpClient.reset(new QTcpSocket); connect(m_tcpClient.data(), SIGNAL(readyRead()), this, SLOT(readData())); this->m_tcpClient->setPauseMode(QAbstractSocket::PauseMode::PauseNever); this->m_tcpClient->setProxy(QNetworkProxy::DefaultProxy); m_tcpClient->flush(); m_tcpClient->abort(); m_tcpClient->connectToHost(QHostAddress(ip), port); } bool TestTcp::testStart(QString pStr) { if (!m_tcpClient.isNull()&&this->m_tcpClient->isValid()) { int ret = m_tcpClient->write(pStr); m_tcpClient->flush(); if (-1 == ret) return false; } return false; } void TestTcp::readData() { emit has_received(); } class CtrlTcp: public QObject { public: CtrlTcp()=default; ~CtrlTcp()override =default; public slots: void init(); void StartT(); public: void testSignal(); private: QScopedPointer<TCPCommander> m_tcpUsage{Q_NULLPTR}; }; CtrlTcp::CtrlTcp() { this->init();// (3) } void CtrlTcp::init() { m_tcpUsage.reset(new TestTcp()); //(4) const auto&[IpAddr,IpPort]=std::tuple{QStringLiteral("192.168.34.18"),13}) m_tcpUsage->init(IpAddr, IpPort); connect(m_tcpUsage.data(), &TCPCommander::tcpConnect, this, &CtrlDetection::tcpConnect); connect(m_tcpUsage.data(), &TCPCommander::tcpStateChange, this, &CtrlDetection::tcpStateChange); connect(m_tcpUsage.data(), &TCPCommander::testComplete, this, &CtrlDetection::testComplete); } void CtrlTcp::StartT() { emit testSignal(); this->m_tcpUsage.testStart(QStringLiteral("ffff")); //(5) } int main() { QThread ctrlTcpTh; auto worker=new CtrlTcp();// (1) worker->moveToThread(&ctrlTcpTh); // (2) connect( thread, &QThread::started, worker, &Worker::StartT); connect( worker, &Worker::finished, ctrlTcpTh, &QThread::quit); connect( worker, &Worker::finished, worker, &Worker::deleteLater); connect( thread, &QThread::finished, ctrlTcpTh, &QThread::deleteLater); }
previously, I have been told that QTcpSocket cannot used in different thread. details of this link. to be concrete,
1.you can use it in a non-main thread, but only the thread in which it was created in.
2.you cannot call different functions on the QTcpSocket from different threads, e.g. read in one thread, write in the other. Instead, you can make a seperate thread for each QTcpSocket, which keeps them from using up time and resources that could be painting your widgets in the main thread.
Hence, I have confused with my project that have been created in span of days.
There are some problems ,which have some controversy in my mind:
(1): Does QTcpSocket has a creation and usage in different thread in my above code in term of (1) ,(2),(3),(4),(5).
(2). Dose Object m_tcpClient read and write has same thread.
(3).Does the signal of has_received is sent from main thread or thread ctrlTcpTh
(4).should the slots function that will be connected to signal has_received have queue connection if the signal of has_received is sent from thread ctrlTcpThThanks for everyone, bro.
-
Since in your example QTcpSocket and TestTcp live in the main thread, the signals are also handled there.
Why is a thread here needed at all? Don't see any advantage, just a lot of code which is error prone.
-
You must not create and delete a QTcpSocket in one thread and use it in another one. Create and delete the socket in the worker thread.
-
@Christian-Ehrlicher Thanks, as with the above code indicated, the object m_tcpUsage is seems to be created in worker thread(main thread). as the sequence of this, May I could consider that the object m_tcpClient was created in worker thread? Hence, the slots function StartT was executed in another thread. In term of this, the member function testStart of object m_tcpUsage is used in another thread, is it right? will it result in the matter that member write function of object m_tcpClient is used in another thread?.
-
@Silent_Alex said in QTcpSocket and Multi-thread:
will it result in the matter that member write function of object m_tcpClient is used in another thread?.
You also must not use a QTcpSocket from outside the thread it was created in.
-
@Christian-Ehrlicher It's simply means that my code is error?
-
@Silent_Alex said in QTcpSocket and Multi-thread:
It's simply means that my code is error?
Since you don't move the socket to the thread you're accessing it later on, yes.
-
@Christian-Ehrlicher Thanks, the last question is that the signal has_received() that was sent from function readData that is corresponding to signal readyread, which is worked in worker thread or ctrlTcpTh?
-
Since in your example QTcpSocket and TestTcp live in the main thread, the signals are also handled there.
Why is a thread here needed at all? Don't see any advantage, just a lot of code which is error prone.
-
@Christian-Ehrlicher Actually, It's just a minimal demon abstracted from another project that was not coding by me. In a word, thanks bro!