之前写过两篇关于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));
}
三、程序运行效果:
Server 的初始化在新的线程中(1),接受客户端连接也在新的线程中(2)。
Client 的初始化在新的线程中(1),接收服务器数据也在新的线程中(2)。
欢迎大家关注公众号:Pou光明
如需完整程序,后台留下联系方式。