多線程中使用QTcpSocket
在run()方法中new QTcpSocket;然后監聽readyRead()信號connect(m_pTcpSocket,SIGNAL(readyRead()),this,SLOT(sloat_RecvData()));
問題是當需要給服務器發送一段命令時(使用m_pTcpSocket->write(byteArray);)程序會報出警告QSocketNotifier: socket notifiers cannot be enabled from another thread。
我在QThread的子類WorkerThread中使用QTcpSocket來連接TCP服務器並給服務器發送數據。
void WorkerThread::run()
{
m_pTcpSocket = new QTcpSocket();
while (1) {
…;
m_pTcpSocket->connectToHost(QHostAddress::LocalHost, 8001); // 連接服務器
m_pTcpSocket->waitForConnected(3000); // 等待確保連接成功
int nByteWrite = m_pTcpSocket->write(strMessage.toUtf8()); // 發送數據到服務器
}
}
可以連接到服務器,但是調用write發送數據時,服務端一直接收不到,表示這里發送失敗了,客戶端發不出數據了~
解決:
后來在使用完write()方法后,再使用flush()方法,就可以發送消息了。
qt的官方文檔里說,調用了flush()方法后,可以把緩沖的數據立刻發送出去。
估計QTcpSocket中的write()方法是帶有緩沖的。
void WorkerThread::run()
{
m_pTcpSocket = new QTcpSocket();
while (1) {
…;
m_pTcpSocket->connectToHost(QHostAddress::LocalHost, 8001);
m_pTcpSocket->waitForConnected(3000);
int nByteWrite = m_pTcpSocket->write(strMessage.toUtf8());
m_pTcpSocket->flush();
}
}
上面的客戶端TcpSocket成功地將數據write發送給了服務端,但是又發現客戶端readyRead信號一直不進它的槽函數sloat_RecvData()。真是一波剛平一波又起啊,現在客戶端又收不到數據了~
解決:
檢查connect(tcpSocket, SIGNAL(readyRead()),this,SLOT(update_message()));返回值為true,說明信號槽連接起來了~
服務端檢查write函數的返回值,為非零,說明也發出去了~
線程while(1)循環很快,在該循環中,循環過快,導致connect來不及處理數據,所以使用waitForReadyRead()將循環進行阻塞,當有數據讀入時取消阻塞,進入下一輪循環。
void WorkerThread::run()
{
m_pTcpSocket = new QTcpSocket();
while (1) {
…;
m_pTcpSocket->connectToHost(QHostAddress::LocalHost, 8001);
m_pTcpSocket->waitForConnected(3000);
int nByteWrite = m_pTcpSocket->write(strMessage.toUtf8());
m_pTcpSocket->flush();
m_pSocket->waitForReadyRead();
}
}
在多線程中是socket,確實挺棘手的!記錄一下,僅供參考~