最近写一个项目用到了服务器开启多线程,阅博客无数,奈何没有理解精髓,致晚上梦见自己写出来了。次日,奋笔疾书,埋头苦学,最后终于写出来了。现在总结一下。
服务器多线程需要用到: QTcpServer QTcpSocket QThread
QTcpServer 最主要的一个incomingConnection虚函数的重写
- 自定义一个client类继承于QTcpSocket :用于解析和发送数据
- 自定义一个server类继承于QTcpSwever:重写虚函数void incomingConnection(),用于接收客户端的连接(取代没有线程的newconnect)
- 自定义一个thread继承于QThread:主要用于处理client里面的数据,重写void run()
- widget主要用于端口的连接等
当QTcpServer监听到一个可用的连接时,会有一个socket descriptor 。
也就是说服务端监听到一个连接,就会有一个唯一的描述标识,依据这个标识会创建一个QTcpSocket。
QTcpSocket
myclient.h
#ifndef MYCLICENT_H
#define MYCLICENT_H
#include <QTcpSocket>
#include <QObject>
class MyClicent : public QTcpSocket
{
Q_OBJECT
public:
explicit MyClicent(qintptr socketdesc,QObject *parent = nullptr);
void on_connected();
QByteArray arraybuffer;
signals:
public slots:
void on_discon();
};
#endif // MYCLICENT_H
myclient.cpp
//处理收发,监听等
#include "myclicent.h"
#include <QDataStream>
#include <QDebug>
#include <QString>
MyClicent::MyClicent(qintptr socketdesc,QObject *parent) : QTcpSocket(parent)
{
this->setSocketDescriptor(socketdesc);
// this->on_connected();
connect(this,&MyClicent::readyRead,this,&MyClicent::on_connected);
this->connect(this,SIGNAL(disconnected()),this,SLOT(on_discon()));
}
void MyClicent::on_connected()
{
qDebug()<<"send success!";
QByteArray array = this->readAll();//QByteArray转浮点数据
arraybuffer.append(array);
qDebug()<<arraybuffer.size()<<array.size();
if(arraybuffer.size()<3360000*4)
return;
float * data_2 = new float[3360000];
memcpy(data_2,arraybuffer.data(),3360000*4);
for(int i = 0;i<10;i++)
{
qDebug()<<"data[1]:"<<data_2[i]<<endl;
}
}
void MyClicent::on_discon()
{
qDebug()<<"disconnect!";
}
MyServer.h
#ifndef MYSERVER_H
#define MYSERVER_H
#include <QTcpServer>
#include <QObject>
#include "mythread.h"
#include "myclicent.h"
class MyServer : public QTcpServer
{
Q_OBJECT
public:
explicit MyServer(QObject *parent = nullptr);
MyClicent *client;
signals:
protected:
virtual void incomingConnection(qintptr socketDescriptor);
public slots:
};
#endif // MYSERVER_H
MyServer.cpp
#include "myserver.h"
#include <QMessageBox>
MyServer::MyServer(QObject *parent) : QTcpServer(parent)
{
}
void MyServer::incomingConnection(qintptr socketDescriptor)
{
QMessageBox::about(0,"提示","有新连接");
client = new MyClicent(socketDescriptor);
MyThread * thread=new MyThread(socketDescriptor,0);
connect(thread, &MyThread::finished, [&]{
qDebug() << "thread is over";
});
connect(thread, &MyThread::finished, &MyThread::deleteLater);
thread->start();
}
MyThread.h
#include "myserver.h"
#include <QMessageBox>
MyServer::MyServer(QObject *parent) : QTcpServer(parent)
{
}
void MyServer::incomingConnection(qintptr socketDescriptor)
{
QMessageBox::about(0,"提示","有新连接");
client = new MyClicent(socketDescriptor);
MyThread * thread=new MyThread(socketDescriptor,0);
connect(thread, &MyThread::finished, [&]{
qDebug() << "thread is over";
});
connect(thread, &MyThread::finished, &MyThread::deleteLater);
thread->start();
}
MyThread.cpp
#include "mythread.h"
MyThread::MyThread(qintptr socketdesc,QObject *parent) : QThread(parent)
{
qDebug()<<"QThread is still";
this->ptr=socketdesc;
}
void MyThread::run()
{
qDebug()<<"开始新线程";
MyClicent * socket=new MyClicent(this->ptr,0);
socket->waitForBytesWritten();
this->exec();
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QTcpSocket>
#include <QTcpServer>
#include <QWidget>
#include <QHostAddress>
#include "myserver.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
// QTcpServer *tcpserver = NULL;
// QTcpSocket *tcpsocket = NULL;
MyServer *server;
};
#endif // WIDGET_H
widget.cpp
//服务器的步骤和函数
//1.建立套接字 2.监听listen(QHostAddress,888) 3.建立连接newConnection
//4.netPendingconnection,peerAdress,peerPort 5.建立连接不断监听readyread
//6.QByteArray array = tcpsocket->readAll();
//参考连接:https://blog.csdn.net/qqwangfan/article/details/78271110?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1
//https://blog.csdn.net/wayrboy/article/details/83108755
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
server = new MyServer(this);
//监听,建立连接套接字
this->server->listen(QHostAddress::Any,8888);
}
Widget::~Widget()
{
delete ui;
}