赞
踩
该程序主要实现tcp服务器如何使用多线程的方式来连接多个客户端,此文章没有实现客户端的多线程编程。
创建子线程时需要注意的点:
1、子线程与主线程之间交互数据时,应采用信号槽的方式
2、子线程中实例化的对象,不应出现在其他线程当中
3、子线程需加入QThread::exec()事件循环函数
4、子线程的销毁关联窗口的销毁信号,调用exit()、quit()、deleteLater()
期间所遇到的问题:
1、之前的思路是想在子线程当中去监听客户端的连接以及数据处理,后面发现在子线程中关联的readyRead()信号始终无法接收到,随后改为在主线程中监听客户端的连接,在子线程中只处理数据
2、子线程对象的实例化也需要注意,需在newConnection()连接的槽函数进行连接,否则客户端断开与服务端的连接后,再次连接时可能无法通信
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "mytcpserver.h" #include <QTcpServer> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); myTcpServer *mytcp_t; QTcpServer *server; QTcpServer *server_com2; tcp_server1 *mytcp_com2; int port; private: Ui::MainWindow *ui; private slots: void on_bt_listen_clicked(); }; #endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QNetworkInterface> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); foreach (QHostAddress info, QNetworkInterface::allAddresses()) { qDebug()<<info.toString(); if(info.toString().size() == 12) { ui->ld_severip->setText(info.toString()); } } } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_bt_listen_clicked() { qDebug()<<QString::fromLocal8Bit("主线程地址:")<<QThread::currentThreadId(); port = ui->ld_port->text().toShort(); //实例服务器对象 server = new QTcpServer(); server_com2 = new QTcpServer(); //监听端口 server->listen(QHostAddress::Any, port); server_com2->listen(QHostAddress::Any, port+2); //连接新连接信号,关联线程的启动 connect(server, &QTcpServer::newConnection, this, [=]{ mytcp_t = new myTcpServer(server); //启动子线程 mytcp_t->start(); }); connect(server_com2, &QTcpServer::newConnection, this, [=]{ mytcp_com2 = new tcp_server1(server_com2); mytcp_com2->start(); }); //线程的销毁 connect(this, &MainWindow::destroyed, this, [=]{ mytcp_t->exit(); mytcp_t->quit(); mytcp_t->deleteLater(); mytcp_com2->exit(); mytcp_com2->quit(); mytcp_com2->deleteLater(); }); }
mytcpserver.h
#ifndef MYTCPSERVER_H #define MYTCPSERVER_H #include <QTcpServer> #include <QTcpSocket> #include <QThread> #include "dataprocess.h" class myTcpServer: public QThread { Q_OBJECT public: explicit myTcpServer(QTcpServer *parent); void run() override; private: void WriteCmd(int _cmd); signals: protected: QTcpServer *server; QTcpSocket *socket; QString rcv; dataprocess *anysis_data; public slots: void getAddrlist(QStringList addr_list); }; class tcp_server1: public QThread { Q_OBJECT public: explicit tcp_server1(QTcpServer *parent); void run() override; protected: QTcpServer *server; QTcpSocket *socket; QString rcv; }; #endif // MYTCPSERVER_H
mytcpserver.cpp
#include "mytcpserver.h" #include <QDebug> #include <QThread> QString cmd_reset = "AT+RESET\r\n"; myTcpServer::myTcpServer(QTcpServer *parent) { server = parent; } void myTcpServer::run() { bool res = false; qDebug()<<QStringLiteral("子线程地址:")<<QThread::currentThreadId(); socket = new QTcpSocket(); socket = server->nextPendingConnection(); anysis_data = new dataprocess; res = connect(socket, &QTcpSocket::readyRead, [=](){ int cnt = 0; rcv = socket->readAll(); //DataAnysis(rcv); cnt = anysis_data->DataAnysis(rcv); WriteCmd(cnt); qDebug()<<"have already receive data"; }); connect(socket, &QTcpSocket::disconnected, [=](){ qDebug()<<"Disconnected"; }); qDebug()<<res; // 进入事件循环 exec(); } void myTcpServer::WriteCmd(int _cmd) { switch(_cmd) { case 1: break; case 2: break; case 3: break; } } void myTcpServer::getAddrlist(QStringList addr_list) { qDebug()<<addr_list[0]; } tcp_server1::tcp_server1(QTcpServer *parent) { server = parent; } void tcp_server1::run() { bool res = false; qDebug()<<QStringLiteral("子线程地址:")<<QThread::currentThreadId(); socket = new QTcpSocket(); socket = server->nextPendingConnection(); res = connect(socket, &QTcpSocket::readyRead, [=](){ rcv = socket->readAll(); //DataAnysis(rcv); qDebug()<<"have already receive data"; }); connect(socket, &QTcpSocket::disconnected, [=](){ qDebug()<<"Disconnected"; }); qDebug()<<res; // 进入事件循环 exec(); }
dataprocess.h
#ifndef DATAPROCESS_H #define DATAPROCESS_H #include <QObject> #include <QString> #include <QTcpSocket> class dataprocess: public QObject { Q_OBJECT public: explicit dataprocess(); //~dataprocess(); int DataAnysis(QString str); private: QTcpSocket *socket; QStringList strlist; signals: void moveAddrlist(QStringList addrlist); }; #endif // DATAPROCESS_H
dataprocess.cpp
#include "dataprocess.h" dataprocess::dataprocess() { } int dataprocess::DataAnysis(QString str) { if(str == "AT-RESET:OK\r\n") { qDebug()<<"Module Init Success"; } else if(str == "AT-LOGO:BT11P31\r\n") { qDebug()<<"Init output Success"; } else if(str == "AT-SSCANN:OK\r\n") { qDebug()<<"Scann cmd send"; } else if(str.contains("AT-SCANI:OK")) { } else if(str.contains(QString("AT-SCANRP:"))) { strlist.push_back(str.mid(10, 12)); emit moveAddrlist(strlist); qDebug()<<strlist[0]; } else { } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。