该程序主要实现tcp服务器如何使用多线程的方式来连接多个客户端,此文章没有实现客户端的多线程编程。
创建子线程时需要注意的点:
1、子线程与主线程之间交互数据时,应采用信号槽的方式
2、子线程中实例化的对象,不应出现在其他线程当中
3、子线程需加入QThread::exec()事件循环函数
4、子线程的销毁关联窗口的销毁信号,调用exit()、quit()、deleteLater()
服务端
1.MainWindow定义
#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
2.MainWindow实现
#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(this);
server_com2 = new QTcpServer(this);
//监听端口
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();
});
}
3.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
4.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();
}
5.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
6.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;
}