Qt 线程中使用socket
- 啊南
- 302阅读
- 2021.01.18
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)); }
Client 的初始化在新的线程中(1),接收服务器数据也在新的线程中(2)。