第12章:Thread_App_Server

1,多线程应用实例服务器

2,源码:

#ifndef TIMESERVER_H
#define TIMESERVER_H

#include <QObject>
#include <QTcpServer>
#include "timethread.h"
#include "mainwindow.h"

class MainWindow;
class TimeServer : public QTcpServer
{
    Q_OBJECT

public:
    TimeServer(QObject *parent);
    MainWindow *mainWindow;

protected:
    void incomingConnection(int socketDescriptor);   //重写此虚函数,这个函数在TCP服务端有新的连接是被调用
};

#endif // TIMESERVER_H
#include "timeserver.h"


TimeServer::TimeServer(QObject *parent): QTcpServer(parent)
{
    mainWindow = (MainWindow *)parent;
}


void TimeServer::incomingConnection(int socketDescriptor)
{
    TimeThread *thread = new TimeThread(socketDescriptor, 0);

    connect(thread, SIGNAL(finished()), mainWindow, SLOT(slotShow()));
    //将上述创建的线程结束消息函数finished()关联到线程自身的槽函数deleteLater()用于结束线程,此操作中,因为信号是在同一个线程中的,
    //所以使用了直接连接方式,故最后一个参数可以省略而使用Qt的自动连接选择方式
    //由于工作线程中存在网络上网络时间,所以不能被外界线程销毁,这里使用了延迟销毁韩式deleteLater()保证由工作线程自身销毁
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()), Qt::DirectConnection);

    //启动上述创建的线程
    thread->start();
}
#ifndef TIMETHREAD_H
#define TIMETHREAD_H

#include <QObject>
#include <QThread>
#include <QtNetwork>
#include <QTcpSocket>
#include <QDateTime>
#include <QByteArray>
#include <QDataStream>



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
#include "timethread.h"

TimeThread::TimeThread(int socketDescriptor, QObject *parent) : QThread(parent), socketDescriptor(socketDescriptor)
{

}


void TimeThread::run()
{
    QTcpSocket tcpSocket;                                   //创建一个QTcpSocket类

    if (!tcpSocket.setSocketDescriptor(socketDescriptor))   //将以上创建的QTcpSocket类置以从构造函数中传入的套接字描述符
    {                                                       //用于向客户端传回服务器端的当前时间
        emit error(tcpSocket.error());                      //如果出错,则发送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();                         //等待返回
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMessageBox>
#include "timeserver.h"

namespace Ui {
class MainWindow;
}
class TimeServer;
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
public slots:
    void slotShow();

private:
    Ui::MainWindow *ui;

    TimeServer *timeServer;
    int count;
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    count = 0;
    timeServer = new TimeServer(this);


    if (!timeServer->listen())
    {
        QMessageBox::critical(this, tr("多线程时间服务器"),tr("无法启动服务器: %1.").arg(timeServer->errorString()));

        close();

        return;
    }
    ui->port->setText(QString::number(timeServer->serverPort()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::slotShow()
{
    ui->nums->setText(QString::number(++count));
}

3,效果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/ksmtnsv37297/article/details/86675486