之前寫過兩篇關于qt線程中使用socket的文章,昨天有小夥伴看了文章之後和我讨論,然後我發現有一篇文章有問題,今天特地更正一下,誤導了之前的小夥伴表示歉意。
Qt中将socket放到線程中運作目前我知道比較好的方式還是使用MoveToThread。不過要注意的是隻有slot_initSocket()槽中的函數是運作在新的線程中的。就像繼承QThread重新實作run()函數一樣,隻有run()裡面的是運作線上程中一樣。
程式示例:
m_socketClient.moveToThread(&m_thread);
connect(&m_thread, SIGNAL(started()), &m_socketClient, SLOT(slot_initSocket()));
m_thread.start();
複制
經過Qt封裝的socket我們使用起來非常友善,有資料到來可以讀取後就會觸發槽函數,如果使用繼承QThread重新實作run()函數的方式,就會不可避免的遇到無法舒服使用信号和槽的情況。而使用MoveToThread則可以規避上面的問題——我們将socket的初始化放到slot_initSocket()函數中,則socket的初始化則是線上程中完成的,那麼對應裡面信号和槽的連接配接也是運作在新線程中的。
程式示例:
connect(mp_clsTcpSocket,SIGNAL(readyRead()),this,SLOT(slot_recvServerData()));
經過上面的操作,我們的socket就可以運作線上程中了。Qt官方也非常推薦使用moveToThread函數。
示例程式是之前socket拆包、處理粘包程式的修改,大家有興趣可以了解下。伺服器端是接收圖檔、用戶端發送圖檔,下面程式是用戶端部分。
老規矩,貼下程式,友善了解:
一、繼承QObject的socket 用戶端程式
MySocketClient::MySocketClient(QObject *parent) : QObject(parent)
{
mp_clsTcpSocket = new QTcpSocket(this);
}
void MySocketClient::slot_recvServerData()
{
QByteArray data = mp_clsTcpSocket->readAll();
qDebug() << "------------" << data;
qDebug() << "socket recv thread id:" << QThread::currentThreadId();}
void MySocketClient::slot_writeData(QByteArray str)
{
mp_clsTcpSocket->write(str);
}
void MySocketClient::slot_initSocket()
{
qDebug() << "socket thread id:" << QThread::currentThreadId();
mp_clsTcpSocket->connectToHost("127.0.0.1",8002);
mp_clsTcpSocket->waitForConnected(1000);
connect(mp_clsTcpSocket,SIGNAL(readyRead()),this,SLOT(slot_recvServerData()));
}
複制
二、主線程函數
①構造函數中使用moveToThread
m_socketClient.moveToThread(&m_thread);
connect(&m_thread, SIGNAL(started()), &m_socketClient, SLOT(slot_initSocket()));
m_thread.start();
connect(this, SIGNAL(signal_sendPicrure(QByteArray)),
&m_socketClient,SLOT(slot_writeData(QByteArray)));
複制
②主Ui線程通過信号和槽使用線程中的socket發送資料
void Widget::on_pbn_send_clicked()
{
QString str = "i am from server of main ui";
emit (signal_sendData(str));
}
複制
三、程式運作效果:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICMyYTMvw1dvwlMvwlM3VWaWV2Zh1Wa-cmbw5CcjZ3M3IGZmZmbvw1MxEDOwkTNtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.png)
Server 的初始化在新的線程中(1),接受用戶端連接配接也在新的線程中(2)。
Client 的初始化在新的線程中(1),接收伺服器資料也在新的線程中(2)。