Qt 多執行緒伺服器與客戶端
阿新 • • 發佈:2018-12-05
文章目錄
- 伺服器
- 客戶端
思路
剛開始學是把tcp放到主執行緒的.
現在多執行緒就是把tcp放到新開闢的執行緒即可,和放在主執行緒的操作一樣
伺服器
- 重寫
void QTcpServer :: incomingConnection(qintptr socketDescriptor)
函式
有新連線的時候QTcpServer先呼叫此虛擬函式,引數socketDescriptor
是原始的套接字.獲得原始套接字之後我們便可以進行處理
myserver.h
#ifndef MYSERVER_H #define MYSERVER_H #include <QTcpServer> class MyThread; class MyServer : public QTcpServer { Q_OBJECT public: MyServer(QWidget *parent = 0); virtual void incomingConnection(qintptr socketDescriptor); signals: void sendReceivedFilename(const QString &fileName); }; #endif // MYSERVER_H
myserver.cpp
#include "myserver.h" #include "mythread.h" #include <QDebug> MyServer::MyServer(QWidget *parent) { } void MyServer::incomingConnection(qintptr socketDescriptor) { static int i = 0; MyThread *thread = new MyThread(0, socketDescriptor); thread->start(); connect(thread, &MyThread::finished, [&]{ qDebug() << "thread is over"; }); connect(thread, &MyThread::finished, &MyThread::deleteLater); connect(thread, &MyThread::sendReceivedFileName, this, &MyServer::sendReceivedFilename); }
mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QWidget>
class MyTcpSocket;
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread(QWidget *parent, qintptr socket);
private:
qintptr p;
MyTcpSocket *socket;
virtual void run();
signals:
void sendReceivedFileName(const QString &fileName);
};
#endif // MYTHREAD_H
mythread.cpp
#include "mythread.h"
#include "mysocket.h"
#include <QDebug>
MyThread::MyThread(QWidget *parent, qintptr socket) : QThread(parent)
{
this->p = socket;
connect(this, SIGNAL(finished()), SLOT(deletLater()));
}
void MyThread::run()
{
MySocket *socket = new MySocket(0, this->p);
connect(socket, &MySocket::disconnected, this, &MyThread::quit, Qt::DirectConnection);
connect(socket, &MySocket::sendReceivedFileName, this, &MyThread::sendReceivedFileName);
this->exec();
}
mysocket.h
#ifndef MYSOCKET_H
#define MYSOCKET_H
#include <QTcpSocket>
#include <QFile>
class MySocket : public QTcpSocket
{
Q_OBJECT
public:
MySocket(QWidget *parent, qintptr socket);
//處理新來的連結
public slots:
void on_connected();
public:
QFile *file;
QByteArray inBlock, outBlcok;
int photoCount = 0;
qint64 gotBytes = 0, fileBytes, fileNameSize, bytesReceived;
qint64 fileSize, sendTotalBytes, bytesToWrite, bytesWritten;
QString fileName;
QString receivedMd5;
int socketFlag;
int photoN;
int currentLocation;
QStringList fileNameList;
bool updateVersion;
QString Tips;
bool firstConnection = false;
void replyMd5(bool boole = true);
void sendFile(bool boole = true);
signals:
void sendReceivedFileName(const QString &fileName);
};
#endif // MYSOCKET_H
mysocket.cpp
#include "mysocket.h"
#include <QDataStream>
#include <QCryptographicHash>
#include <QSettings>
#include <QMessageBox>
#include <QDebug>
enum socketFlag{
md5 = 1,
versionFlag
};
MySocket::MySocket(QWidget *parent, qintptr socket) : QTcpSocket(0)
{
this->setSocketDescriptor(socket);
connect(this, SIGNAL(readyRead()), this, SLOT(on_connected()));
bytesReceived = 0;
gotBytes = 0;
fileBytes = 0;
fileNameSize = 0;
connect(this, &MySocket::disconnected, []{
qDebug() << "disconnected";
});
}
void MySocket::on_connected()
{
//讀到資料的操作
qDebug() << "conn";
}
客戶端
h檔案
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "mytcpsockets.h"
#include <QTimer>
class QTcpSocket;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
void on_pushButton_4_clicked();
signals:
void con(const QString &ip, int port);
void discon();
private:
Ui::MainWindow *ui;
QTcpSocket *socket;
QHash<int, QTcpSocket *> m_hash;
MyTcpSockets *m_socket = nullptr;
QTimer tm;
};
#endif // MAINWINDOW_H
cpp檔案
void MainWindow::on_pushButton_4_clicked()
{
//執行緒傳送
int b = ui->listWidget->count();
QThread *th = new QThread;
th->start();
for (int i = 0; i < b; i++)
{
QString fileName = ui->listWidget->item(i)->text();
MySocketTwo *two = new MySocketTwo(fileName, i);
connect(this, &MainWindow::con, two, &MySocketTwo::cnt, Qt::QueuedConnection);
two->moveToThread(th);
}
emit this->con(ui->lineEdit->text(), 6666);
return ;
}
mysockettwo.h
#ifndef MYSOCKETTWO_H
#define MYSOCKETTWO_H
#include <QTcpSocket>
#include <QIODevice>
#include <QHostAddress>
class QFile;
class MySocketTwo : public QTcpSocket
{
Q_OBJECT
public:
MySocketTwo(QString &fileName, int n, QObject *parent = 0);
qint64 totalBytes, receivedBytes, sendBytes;
QByteArray byteArray;
int number = 0;
QFile *file;
QString fileName;
public slots:
void cnt(const QString &ip, const int &port);
signals:
void sendProgress(const int &i, const int &n);
void sendData(const int &i, const QString &str);
};
#endif // MYSOCKETTWO_H
mysockettwo.cpp
#include "mysockettwo.h"
#include <QFile>
#include <QDataStream>
#include <QTcpSocket>
#include <QFileInfo>
#include <QCryptographicHash>
MySocketTwo::MySocketTwo(QString &fileName, int n, QObject *parent) : QTcpSocket(parent),
totalBytes(0), receivedBytes(0), sendBytes(0)
{
//初始化訊號
connect(this, &MySocketTwo::connected, this, &MySocketTwo::newFile);
this->number = n;//分配序號
this->fileName = fileName;
}
void MySocketTwo::cnt(const QString &ip, const int &port)
{
this->connectToHost(ip, port);
qDebug() << this->waitForConnected(5000);
qDebug() << "connect";
}
void MySocketTwo::newFile()
{
//連線上伺服器之後的操作
}