【Qt5开发及实例】33、多线程网络时间服务器

来源:互联网 发布:mac os 10.13 vmtools 编辑:程序博客网 时间:2024/06/06 09:54

项目TimeServer

dialog.h

/*** 书本:【Qt5开发及实例】* 功能:多线程网络时间服务器* 文件:dialog.h* 时间:2015年2月11日22:43:26* 作者:cutter_point*/#ifndef DIALOG_H#define DIALOG_H#include <QDialog>#include <QLabel>#include <QPushButton>class TimeServer;class Dialog : public QDialog{  Q_OBJECTpublic:  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

/*** 书本:【Qt5开发及实例】* 功能:多线程网络时间服务器* 文件:dialog.cpp* 时间:2015年2月11日22:43:26* 作者:cutter_point*/#include "dialog.h"#include "timeserver.h"#include <QHBoxLayout>#include <QVBoxLayout>#include <QMessageBox>Dialog::Dialog(QWidget *parent)  : QDialog(parent){  this->setWindowTitle(tr("多线程时间服务器"));  Label1 = new QLabel(tr("服务器端口:"));  Label2 = new QLabel;  quitBtn = new QPushButton(tr("close"));  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()));}//void slotShow();    //线程在界面的显示,线程结束的时候调用void Dialog::slotShow(){  //显示这是第几次请求,也就是第几次调用线程执行这个函数  Label2->setText(tr("第%1次请求完毕.").arg(++count));}Dialog::~Dialog(){}


timeserver.h

/*** 书本:【Qt5开发及实例】* 功能:多线程网络时间服务器* 文件:timeserver.h* 时间:2015年2月11日23:17:43* 作者:cutter_point*/#ifndef TIMESERVER_H#define TIMESERVER_H#include <QTcpServer>class Dialog;class TimeServer : public QTcpServer{  Q_OBJECTpublic:  explicit TimeServer(QObject *parent = 0);signals:public slots:protected:  void incomingConnection(int socketDescriptor);    //当tcp有新的连接的时候调用,其参数为所接收新连接的套接字描述符private:  Dialog *dlg;    //界面};#endif // TIMESERVER_H


timeserver.cpp

/*** 书本:【Qt5开发及实例】* 功能:多线程网络时间服务器* 文件:timeserver.cpp* 时间:2015年2月11日23:18:08* 作者:cutter_point*/#include "timeserver.h"#include "timethread.h"#include "dialog.h"TimeServer::TimeServer(QObject *parent) :  QTcpServer(parent){  //初始化界面  dlg = (Dialog *)parent; //转化为dialog前面的对象的指针}//void incomingConnection(int socketDescriptor);    //当tcp有新的连接的时候调用,其参数为所接收新连接的套接字描述符void TimeServer::incomingConnection(int socketDescriptor){  //有一个新连接的时候,就相应的创建一个对应的线程  TimeThread *thread = new TimeThread(socketDescriptor);  //线程结束的时候,要通知界面的显示  connect(thread, SIGNAL(finished()), dlg, SLOT(slotShow()));  //同时销毁结束线程  connect(thread, SIGNAL(finished()), dlg, SLOT(deleteLater()));  //启动线程  thread->start();}


timethread.h


/*** 书本:【Qt5开发及实例】* 功能:多线程网络时间服务器* 文件:timethread.h* 时间:2015年2月11日22:43:26* 作者:cutter_point*/#ifndef TIMETHREAD_H#define TIMETHREAD_H#include <QThread>#include <QtNetwork>#include <QTcpSocket>class TimeThread : public QThread{  Q_OBJECTpublic:  explicit TimeThread(int socketDescriptor, QObject *parent = 0);  void run();   //继承来的,线程执行的内容signals:  //如果出错的话可以给出错误信息  void error(QTcpSocket::SocketError socketError);public slots:private:  int socketDescriptor;   //套接字描述符};#endif // TIMETHREAD_H

timethread.cpp

/*** 书本:【Qt5开发及实例】* 功能:多线程网络时间服务器* 文件:timethread.cpp* 时间:2015年2月11日22:43:26* 作者:cutter_point*/#include "timethread.h"#include <QDateTime>    //时间#include <QByteArray>   //协议传输的字节流#include <QDataStream>    //数据流TimeThread::TimeThread(int socketDescriptor, QObject *parent) :  QThread(parent), socketDescriptor(socketDescriptor)     //初始化{}void TimeThread::run()    //线程执行开始的函数{  QTcpSocket tcpSocket;     //创建一个tcp套接字  if(!tcpSocket.setSocketDescriptor(socketDescriptor))    //如果套接字描述符操作失败    {      emit error(tcpSocket.error());    //发出错误信号      return;   //结束    }  QByteArray block;   //字节数组,这个block应该是一个指向第一个位置的指针  QDataStream out(&block, QIODevice::WriteOnly);    //数据流,数据流操作block,这里block指针??  out.setVersion(QDataStream::Qt_5_3);    //版本= =  uint time2u = QDateTime::currentDateTime().toTime_t();    //得到系统的时间,并传换成时间的格式  out<<time2u;    //输入到字节流中  tcpSocket.write(block);   //把字节流写到协议端口  tcpSocket.disconnectFromHost();   //断开端口连接  tcpSocket.waitForDisconnected();    //默认时间,等待客户端返回信息}


项目TimeClient


timeclient.h

/*** 书本:【Qt5开发及实例】* 功能:多线程网络时间服务器* 文件:timeclient.h* 时间:2015年2月11日23:49:56* 作者:cutter_point*/#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_OBJECTpublic:  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;      //tcp套接字};#endif // TIMECLIENT_H


timeclient.cpp

/*** 书本:【Qt5开发及实例】* 功能:多线程网络时间服务器* 文件:timeclient.cpp* 时间:2015年2月11日23:49:56* 作者:cutter_point*/#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("close"));  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();   //键盘焦点对准这个控件}//void enableGetBtn();    //按钮的控制void TimeClient::enableGetBtn(){  getBtn->setEnabled(!serverNameLineEdit->text().isEmpty()&&!portLineEdit->text().isEmpty());}//void getTime();   //准备得到时间void TimeClient::getTime(){  //得到时间之前,按下了按钮就不能再按了  getBtn->setEnabled(false);  //初始化这边的时间和套接字,等会用来接收数据  time2u = 0;  tcpSocket->abort();  //连接上相应的服务器和端口,准备连接  tcpSocket->connectToHost(serverNameLineEdit->text(), portLineEdit->text().toInt());}//void readTime();    //读取时间过来void TimeClient::readTime(){  //获得到了数据就读取  //初始化一个数据流,对端口的套接字操作  QDataStream in(tcpSocket);  in.setVersion(QDataStream::Qt_5_3);   //版本!!!!  //时间如果开始初始化为0了,那么就重新获取  if(time2u == 0)    {      if(tcpSocket->bytesAvailable() < (int)sizeof(uint))        return;   //得到的数据不和常理的话,直接结束      in>>time2u;   //把数据输出到time2u中    }  //不为零,那么就继续用  dateTimeEdit->setDateTime(QDateTime::fromTime_t(time2u));  //按钮设置为可以按  getBtn->setEnabled(true);}//void showError(QAbstractSocket::SocketError socketError);   //出错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);}TimeClient::~TimeClient(){}


0 0