QT network communication multi-thread
-
- QThread thread creation method
- the code
QThread thread creation method
1. Write a class that inherits the QThread class, rewrite the run() function, and generate an instance of ChildThread in the main thread, and call the start() function of the object
Every time you create a new thread, you need to inherit QThread, implement a new class, and perform resource management, thread release and deletion by yourself.
2. Define an ordinary QObject derived class Worker, then move its object to the created QThread class, and call the start() function of the thread
If the main thread wants to run calculations in the child thread, it must be called by signaling, or through the signal of the control
Code
Implement file transfer function
Service-Terminal:
main thread:
class Widget : public QWidget {<!-- --> Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); private: Ui::WidgetClass *ui; QTcpServer* serv; public slots: void setListen_clicked(); };
Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::WidgetClass()) {<!-- --> //initialization ui->setupUi(this); ui->port->setText("8899"); setWindowTitle("Server"); serv = new QTcpServer(this); //Accept new connections when listening to new connections connect(serv, &QTcpServer::newConnection, this, [=]() {<!-- --> QTcpSocket* conntcp = serv->nextPendingConnection(); ui->msg->append("Establish a connection with the client"); //Create a child thread and run it ReceiveFile* subThread = new ReceiveFile(conntcp); subThread->start(); //After the task is completed, recycle the child thread resources connect(subThread, & amp;ReceiveFile::over, this, [=]() {<!-- --> subThread->exit(); subThread->wait(); subThread->deleteLater(); ui->msg->append("The file has been received"); QMessageBox::information(this, "File received", "File received"); }); }); // button handling connect(ui->setListen, &QPushButton::clicked, this, &Widget::setListen_clicked); } Widget::~Widget() {<!-- --> delete ui; } void Widget::setListen_clicked() {<!-- --> unsigned short port = ui->port->text().toUShort(); serv->listen(QHostAddress::Any, port); }
Child thread accepts files
class ReceiveFile : public QThread {<!-- --> Q_OBJECT public: ReceiveFile(QTcpSocket* tcp, QObject *parent=nullptr); ~ReceiveFile(); protected: void run() override;//Rewrite thread running function private: QTcpSocket* tcp_; signals: void over(); };
ReceiveFile::ReceiveFile(QTcpSocket* tcp, QObject* parent) : QThread(parent), tcp_(tcp) {<!-- -->} ReceiveFile::~ReceiveFile() {<!-- -->} void ReceiveFile::run() {<!-- --> QFile* file = new QFile("recv.txt"); file->open(QFile::WriteOnly); // read and write to file when ready connect(tcp_, &QTcpSocket::readyRead, this, [=]() {<!-- --> static int count = 0; static int total = 0; if (count == 0) {<!-- --> tcp_->read((char*) & amp;total, 4);//read file size } QByteArray all = tcp_->readAll(); count + = all. size(); file->write(all); //Release resources after writing if (count == total) {<!-- --> tcp_->close(); tcp_->deleteLater(); file->close(); file->deleteLater(); emit over(); } }); exec();//event loop }
client:
main thread
class Widget : public QWidget {<!-- --> Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); private: Ui::WidgetClass *ui; public slots: void connect_clicked(); void sendFile_clicked(); void setFile_clicked(); signals: void startConnect(QString ip, unsigned short port); void sendFile(QString path); };
Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::WidgetClass()) {<!-- --> //initialization ui->setupUi(this); ui->port->setText("8899"); ui->ip->setText("127.0.0.1"); setWindowTitle("Client"); ui->progressBar->setRange(0, 100); ui->progressBar->setValue(0); //Create a child thread and put the running object into the thread QThread* t = new QThread; SendFile* worker = new SendFile; worker->moveToThread(t); //Click the button, the child thread sends the file connect(this, & amp;Widget::sendFile, worker, & amp;SendFile::sendFile); //Click the button, the child thread connects to the server connect(this, & amp;Widget::startConnect, worker, & amp;SendFile::connectServer); //The connection is successful, the main thread prints the message connect(worker, & amp;SendFile::connectOk, this, [=]() {<!-- --> QMessageBox::information(this, "connected to the server", "connected successfully");//message dialog box }); //Disconnect, the main thread recycles resources connect(worker, & amp;SendFile::gameover, this, [=]() {<!-- --> //Release resources t->quit(); t->wait(); worker->deleteLater(); t->deleteLater(); }); //The main thread displays the sending progress connect(worker, &SendFile::curPercent, ui->progressBar, &QProgressBar::setValue); // button handling connect(ui->connect, &QPushButton::clicked, this, &Widget::connect_clicked); connect(ui->setFile, & amp;QPushButton::clicked, this, & amp;Widget::setFile_clicked); connect(ui->sendFile, &QPushButton::clicked, this, &Widget::sendFile_clicked); //The child thread starts running t->start(); } Widget::~Widget() {<!-- --> delete ui; } void Widget::connect_clicked() {<!-- --> QString ip = ui->ip->text(); unsigned short port = ui->port->text().toUShort(); emit startConnect(ip, port); } void Widget::setFile_clicked() {<!-- --> QString path = QFileDialog::getOpenFileName();//File dialog if (path.isEmpty()) {<!-- --> QMessageBox::warning(this, "Open the file", "The file path cannot be empty"); return; } ui->filePath->setText(path); } void Widget::sendFile_clicked() {<!-- --> emit sendFile(ui->filePath->text()); }
The child thread connects to the server and sends the file
class SendFile: public QObject {<!-- --> Q_OBJECT public: SendFile(QObject* parent = nullptr); ~SendFile(); void connectServer(QString ip, unsigned short port); void sendFile(QString path); private: QTcpSocket* tcp; signals: void connectOk(); void gameover(); void curPercent(int num); };
SendFile::SendFile(QObject* parent) : QObject(parent) {<!-- --> } SendFile::~SendFile() {<!-- --> } void SendFile::connectServer(QString ip, unsigned short port) {<!-- --> tcp = new QTcpSocket; tcp->connectToHost(QHostAddress(ip), port); //The connection is successful, notify the main thread connect(tcp, & amp; QTcpSocket::connected, this, & amp; SendFile::connectOk); //Disconnect, recycle resources, and notify the main thread connect(tcp, &QTcpSocket::disconnected, this, [=]() {<!-- --> tcp->close(); tcp->deleteLater(); emit gameover(); }); } void SendFile::sendFile(QString path) {<!-- --> QFile file(path); QFileInfo info(path);//file information int filesize = info.size();//file size file.open(QFile::ReadOnly);//Open the file while (!file.atEnd()) {<!-- -->//End flag static int num = 0; if (num == 0) {<!-- --> tcp->write((char*) & amp;filesize,4);//Send the file size first } QByteArray line = file.readLine();//Read by line num + = line. size(); int percent = (num * 100 / filesize);//percentage emit curPercent(percent); tcp->write(line); } }
result:
refer to:
Qt multi-threaded network communication – station b, big C of love programming