Qt---多執行緒應用的例子
阿新 • • 發佈:2019-02-19
伺服器端
TimeThread建立TcpSocket,負責實現Run()函式,傳送伺服器端資訊,然後斷開連線。
TimeSever中建立TimeThread,實incomingConnection(int socketDescriptor)函式每當有新的客戶端連線時,建立新的執行緒,將執行緒結束函式與對話方塊中的退出按鈕繫結,然後啟動執行緒
Dialog中建立TimeSever,對客戶端監聽
.pro中新增:
QT += network
timethread.h
#ifndef TIMETHREAD_H
#define TIMETHREAD_H
#include <QThread>
#include <QtNetwork>
#include <QTcpSocket>
class TimeThread : public QThread
{
Q_OBJECT
public:
TimeThread(int socketDescriptor,QObject *parent=0);
void run();
signals:
void error(QTcpSocket::SocketError socketError);
private:
int socketDescriptor;
};
#endif // TIMETHREAD_H
timethread.cpp
#include "timethread.h"
#include <QDateTime>
#include <QByteArray>
#include <QDataStream>
TimeThread::TimeThread(int socketDescriptor, QObject *parent)
:QThread(parent), socketDescriptor(socketDescriptor)
{
}
void TimeThread::run()
{
QTcpSocket tcpSocket;
if(!tcpSocket.setSocketDescriptor(socketDescriptor))
{
emit error(tcpSocket.error());
return;
}
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_3);
uint time2u = QDateTime::currentDateTime().toTime_t();
out << time2u;
tcpSocket.write(block);
tcpSocket.disconnectFromHost();
tcpSocket.waitForDisconnected();
}
timeserver.h
#ifndef TIMESERVER_H
#define TIMESERVER_H
#include <QTcpServer>
class Dialog; //伺服器端的宣告
class TimeServer:public QTcpServer
{
Q_OBJECT
public:
TimeServer(QObject *parent = 0);
protected:
void incomingConnection(int socketDescriptor);
private:
Dialog *dlg;
};
#endif // TIMESERVER_H
timeserver.cpp
#include "timeserver.h"
#include "timethread.h"
#include "dialog.h"
TimeServer::TimeServer(QObject *parent): QTcpServer(parent)
{
dlg = (Dialog *)parent;
}
void TimeServer::incomingConnection(int socketDescriptor)
{
TimeThread *thread = new TimeThread(socketDescriptor, 0);
connect(thread, SIGNAL(finished()), dlg, SLOT(slotShow()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()), Qt::DirectConnection);
thread->start();
}
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QPushButton>
class TimeServer;
class Dialog:public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
public slots:
void slotShow();
private:
QLabel *Label1;
QLabel *Label2;
QPushButton *quitBtn;
TimeServer *timeServer;
int count;
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMessageBox>
#include "timeserver.h"
Dialog::Dialog(QWidget *parent): QDialog(parent)
{
setWindowTitle(tr("多執行緒時間伺服器"));
Label1 =new QLabel(tr("伺服器埠:"));
Label2 = new QLabel;
quitBtn = new QPushButton(tr("退出"));
QHBoxLayout *BtnLayout = new QHBoxLayout;
BtnLayout->addStretch(1);
BtnLayout->addWidget(quitBtn);
BtnLayout->addStretch(1);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(Label1);
mainLayout->addWidget(Label2);
mainLayout->addLayout(BtnLayout);
connect(quitBtn, SIGNAL(clicked()), this, SLOT(close()));
count=0;
timeServer = new TimeServer(this);
if(!timeServer->listen())
{
QMessageBox::critical(this,tr("多執行緒時間伺服器"),
tr("無法啟動伺服器:%1.").arg(timeServer->errorString()));
close();
return;
}
Label1->setText(tr("伺服器埠:%1.").arg(timeServer->serverPort()));
}
Dialog::~Dialog()
{
}
void Dialog::slotShow()
{
Label2->setText(tr("第%1次請求完畢。").arg(++count));
}
main.cpp
#include "dialog.h"
#include <QApplication>
/*
*TimeThread建立TcpSocket,負責實現Run()函式,傳送伺服器端資訊,然後斷開連線
*TimeSever中建立TimeThread,實現incomingConnection(int socketDescriptor)函式
*每當有新的客戶端連線時,建立新的執行緒,將執行緒結束函式與對話方塊中的退出按鈕繫結,然後啟動執行緒
*Dialog中建立TimeSever,對客戶端監聽
*/
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
return a.exec();
}
客戶端
初始化中建立socket,點選“獲取時間”按鈕後,socket連線伺服器,
當伺服器傳送來資料時,訊號函式readyRead()執行,觸readTime()函式獲取伺服器端時間。
在讀取資料時,採用QDataStream
.pro
QT += network
timeclient.h
#ifndef TIMECLIENT_H
#define TIMECLIENT_H
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QDateTimeEdit>
#include <QTcpSocket>
#include <QAbstractSocket>
class TimeClient : public QDialog
{
Q_OBJECT
public:
TimeClient(QWidget *parent = 0);
~TimeClient();
public slots:
void enableGetBtn();
void getTime();
void readTime();
void showError(QAbstractSocket::SocketError socketError);
private:
QLabel *serverNameLabel;
QLineEdit *serverNameLineEdit;
QLabel *portLabel;
QLineEdit *portLineEdit;
QDateTimeEdit *dateTimeEdit;
QLabel *stateLabel;
QPushButton *getBtn;
QPushButton *quitBtn;
uint time2u;
QTcpSocket *tcpSocket;
};
#endif // TIMECLIENT_H
timeclient.cpp
#include "timeclient.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QDataStream>
#include <QMessageBox>
TimeClient::TimeClient(QWidget *parent): QDialog(parent)
{
setWindowTitle(tr("多執行緒時間服務客戶端"));
serverNameLabel =new QLabel(tr("伺服器名:"));
serverNameLineEdit = new QLineEdit("Localhost");
portLabel =new QLabel(tr("埠:"));
portLineEdit = new QLineEdit;
QGridLayout *layout = new QGridLayout;
layout->addWidget(serverNameLabel, 0, 0);
layout->addWidget(serverNameLineEdit, 0, 1);
layout->addWidget(portLabel, 1, 0);
layout->addWidget(portLineEdit, 1, 1);
dateTimeEdit = new QDateTimeEdit(this);
QHBoxLayout *layout1 = new QHBoxLayout;
layout1->addWidget(dateTimeEdit);
stateLabel =new QLabel(tr("請首先執行時間伺服器!"));
QHBoxLayout *layout2 = new QHBoxLayout;
layout2->addWidget(stateLabel);
getBtn = new QPushButton(tr("獲取時間"));
getBtn->setDefault(true);
getBtn->setEnabled(false);
quitBtn = new QPushButton(tr("退出"));
QHBoxLayout *layout3 = new QHBoxLayout;
layout3->addStretch();
layout3->addWidget(getBtn);
layout3->addWidget(quitBtn);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(layout);
mainLayout->addLayout(layout1);
mainLayout->addLayout(layout2);
mainLayout->addLayout(layout3);
connect(serverNameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(enableGetBtn()));
connect(portLineEdit, SIGNAL(textChanged(QString)), this, SLOT(enableGetBtn()));
connect(getBtn, SIGNAL(clicked()), this, SLOT(getTime()));
connect(quitBtn, SIGNAL(clicked()), this, SLOT(close()));
tcpSocket = new QTcpSocket(this);
connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readTime()));
connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(showError(QAbstractSocket::SocketError)));
portLineEdit->setFocus();
}
TimeClient::~TimeClient()
{
}
void TimeClient::enableGetBtn()
{
getBtn->setEnabled(!serverNameLineEdit->text().isEmpty() && !portLineEdit->text().isEmpty());
}
void TimeClient::getTime()
{
getBtn->setEnabled(false);
time2u =0;
tcpSocket->abort(); //取消已有連線
tcpSocket->connectToHost(serverNameLineEdit->text(), portLineEdit->text().toInt());
}
void TimeClient::readTime()
{
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_3);
if(time2u==0)
{
if(tcpSocket->bytesAvailable()<(int)sizeof(uint))
return;
in >> time2u;
}
dateTimeEdit->setDateTime(QDateTime::fromTime_t(time2u));
getBtn->setEnabled(true);
}
void TimeClient::showError(QAbstractSocket::SocketError socketError)
{
switch (socketError)
{
case QAbstractSocket::RemoteHostClosedError:
break;
case QAbstractSocket::HostNotFoundError:
QMessageBox::information(this, tr("時間服務客戶端"), tr("主機不可達!"));
break;
case QAbstractSocket::ConnectionRefusedError:
QMessageBox::information(this, tr("時間服務客戶端"), tr("連線被拒絕!"));
break;
default:
QMessageBox::information(this, tr("時間服務客戶端"),tr("產生如下錯誤: %1.").arg(tcpSocket->errorString()));
}
getBtn->setEnabled(true);
}
main.cpp
#include "timeclient.h"
#include <QApplication>
/*
* 初始化中建立socket,點選“獲取時間”按鈕後,socket連線伺服器,
* 當伺服器傳送來資料時,訊號函式readyRead()執行,觸發readTime()函式獲取伺服器端時間
* 在讀取資料時,採用QDataStream
*/
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TimeClient w;
w.show();
return a.exec();
}