项目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_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
- /**
- * 书本:【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_OBJECT
- public:
- 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_OBJECT
- public:
- 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_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; //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()
- {
- }