概述
题目简介:
在现实世界中有一种数据模型,模拟生产者与消费者模型。如火车票售票系统,将票据的数量录入服务器我们称之为“生产”了若干车票。各地终端会共享这些车票信息去售票。直到车票售票完,则提示无票可卖。
本练习题,在同一台电脑上使用不同的进程(独立运行的应用程序)模拟火车票售票系统。将录入存放火车票的独立运行程序我们称之为服务端。一台电脑只能运行一个实例。其他负责售卖火车票的程序称为客户端。客户端程序,一台电脑可以运行多个实例。客户端程序主要的功能就是消费服务端的火车票。
要求:
- 你可以编写带界面的应用程序,也可以编写不带界面的命令行应用程序。
- 当客户端关闭时,服务端能够给予提示,当有客户端启动连接时,服务端给予提示。
- 当客户段消耗一张车票时,服务端提示信息(信息包含那个客户端,什么时候消耗一张票)。
- 假设每个客户端均有一个唯一的编号。
- 客户端是模拟买票,可以使用定时器,设置间隔周期,如2秒消耗一张票。
- 当客户端无票可卖时(服务器的票已经被消耗完),给予提示。
- 当服务器卖完所有的票时给予提示,并统计客户端的卖票情况(每个客户的售票详情,如张数,时间)。
题目难点:
主要考察的是多线程的应用,因为服务器只有一个,不同的客户端购票时间,信息都不相同
开发环境:
QT Creator
//client.h 客户端的界面
#ifndef CLIENT_H
#define CLIENT_H
#include <QWidget>
#include <QTcpSocket>
#include <QLineEdit>
#include <QTextBrowser>
#include <QLabel>
class Client : public QWidget
{
Q_OBJECT
public:
explicit Client(QWidget *parent = 0);
QTcpSocket* _socket;
QLineEdit* _lineEdit1;
QLineEdit* _lineEdit2;
QLineEdit* _lineEdit3;
QLineEdit* _lineEdit4;
QTextBrowser* _show;
QLabel* _lable1;
QLabel* _lable2;
QLabel* _lable3;
QLabel* _lable4;
void countticket();
signals:
public slots:
void slotButtonClick();//购票按钮响应函数
void slotexBtnClick();//退出按钮响应
};
#endif // CLIENT_H
//client.cpp
#include "client.h"
#include "tcpsocket.h"
#include <QWidget>
#include <QGridLayout>
#include <QPushButton>
#include <QTime>
int temp;
int ticketcount = 100;
QByteArray str_data;
Client::Client(QWidget *parent) :
QWidget(parent)
{
_socket = new QTcpSocket(this);
_socket->connectToHost("127.0.0.1", 9988);
_lable1= new QLabel(this);
_lable1->setText("购买票数:");
_lable2= new QLabel(this);
_lable2->setText("乘车时间:");
_lable3= new QLabel(this);
_lable3->setText("始发站:");
_lable4= new QLabel(this);
_lable4->setText("终点站:");
QGridLayout* lay = new QGridLayout(this);
lay->addWidget(_lable1,0,0,1,1);
lay->addWidget(_lable2,2,0,1,1);
lay->addWidget(_lable3,0,1,1,1);
lay->addWidget(_lable4,2,1,1,1);
_lineEdit1 = new QLineEdit(this);
_lineEdit1->setPlaceholderText("请输入两位数,如02:");
_lineEdit2 = new QLineEdit(this);
_lineEdit2->setPlaceholderText("格式如20170724:");
_lineEdit3 = new QLineEdit(this);
_lineEdit3->setPlaceholderText("请输入始发站,如西安:");
_lineEdit4 = new QLineEdit(this);
_lineEdit4->setPlaceholderText("请输入终点站,如西安:");
lay->addWidget(_lineEdit1,1,0,1,1);
lay->addWidget(_lineEdit2,3,0,1,1);
lay->addWidget(_lineEdit3,1,1,1,1);
lay->addWidget(_lineEdit4,3,1,1,1);
QPushButton* button = new QPushButton("购买");
lay->addWidget(button,4,0,1,1);
QPushButton* exBtn = new QPushButton("退出");
lay->addWidget(exBtn,4,1,1,1);
_show = new QTextBrowser(this);
lay->addWidget(_show,5,0,1,2);
connect(button, SIGNAL(clicked()), this, SLOT(slotButtonClick()));//买票
connect(exBtn, SIGNAL(clicked()), this, SLOT(slotexBtnClick()));//退出客户端
connect(_lineEdit4, SIGNAL(returnPressed()), this, SLOT(slotButtonClick()));//使用回车键发送
}
//买票按钮响应
void Client::slotButtonClick()
{
QString strText1 = _lineEdit1->text();
QString strText2 = _lineEdit2->text();
QString strText3 = _lineEdit3->text();
QString strText4 = _lineEdit4->text();
if(strText1.isEmpty())
return;
bool ok;
temp = strText1.toInt(&ok,10);
QString strText = " "+strText1+tr("张")+" "+strText3+tr("-")+strText4+" "+strText2+tr("的票");
_socket->write(strText.toUtf8());
countticket();
_lineEdit1->clear();
_lineEdit2->clear();
_lineEdit3->clear();
_lineEdit4->clear();
}
//退出按钮响应
void Client::slotexBtnClick()
{
//退出前给服务器发送“close”标志
QString strclose = "close";
_socket->write(strclose.toUtf8());
close();
}
//买票具体情况
void Client::countticket()
{
QTime time = QTime::currentTime();
QString str = time.toString("H:mm:ss");
QString strText = _lineEdit1->text();
bool ok;
int temp1 = strText.toInt(&ok,10);
int temp2 = ticketcount-temp1;
if(temp2>=0)
{
ticketcount= ticketcount-temp1;
str_data=QByteArray::number(temp1,10);
_show->append("购买成功,您购买了"+str_data+"张票"+str);
}
else
{
str_data=QByteArray::number(ticketcount,10);
_show->append("购买失败,剩余"+str_data+"张票");
}
}
//server.h 服务器的界面
#ifndef SERVER_H
#define SERVER_H
#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTextBrowser>
#include <QLabel>
#include <QListWidget>
class Tcpserver;
class Server : public QWidget
{
Q_OBJECT
public:
explicit Server(QWidget* parent = 0);
private:
QTcpSocket* _socket;
QTextBrowser* _show;
QLabel* _label;
QList<QString> evetick; //每个乘客买票情况
QListWidget* list;
protected:
signals:
public slots:
void recsell(QByteArray buf,QString byte,QString str_id); //接收tcpserver端传来售票的数据
void slotbuttonClick();//购票统计按钮
};
#endif // SERVER_H
//server.cpp
#include "server.h"
#include "tcpsocket.h"
#include "tcpserver.h"
#include "mainwindow.h"
#include <QTime>
#include <QWidget>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QPushButton>
#include <QDebug>
int ticket = 100;
QString strid_temp;
Server::Server(QWidget *parent) :
QWidget(parent)
{
// 创建服务器并监听
Tcpserver *server = new Tcpserver();
server->listen(QHostAddress::Any,9988);
//接收tcpserver端发送过来的数据
connect(server,SIGNAL(transsell(QByteArray,QString,QString)),this,SLOT(recsell(QByteArray,QString,QString)));
_show = new QTextBrowser;
_show->setMaximumSize(300,300);
_show->setMinimumSize(300,300);
QHBoxLayout* lay = new QHBoxLayout(this);
lay->addWidget(_show,0);
QPushButton* button = new QPushButton("售票统计");
lay->addWidget(button,1);
connect(button, SIGNAL(clicked()), this, SLOT(slotbuttonClick()));
}
//接收函数,接收tcpserver端发送过来的数据
void Server::recsell(QByteArray buf,QString byte,QString str_id)
{
//如果客户端点击 退出 按钮,则断开连接
if(buf == "close")
{
_show->append(str_id+"客户端连接断开......");
}
else
{
//同一客户端只显示一次连接成功
if(strid_temp != str_id)
{
_show->append(str_id+"客户端连接建立成功......");
}
//显示当前时间
QTime time = QTime::currentTime();
QString str_time = time.toString("H:mm:ss");
QString str_buf = buf.mid(1,buf.length()).left(2);
qDebug()<<str_buf;
int temp;
bool ok;
int buf1 = str_buf.toInt(&ok,10 );
QByteArray str_data;
temp = ticket-buf1;//计算剩余票数
if(temp>=0)
{
ticket= ticket-buf1;
str_data=QByteArray::number(ticket,10);
_show->append(str_id+"客户端售出"+str_buf+"张票"+" "+str_time+" "+"还剩"+str_data+"张票");
evetick.push_back(byte);//将每个客户端每次售票情况写入evetick中
}
else
{
temp = -1;
str_data=QByteArray::number(temp,10);
str_data=QByteArray::number(ticket,10);
_show->append("售票失败,还剩"+str_data+"张票");
}
}
strid_temp = str_id;
}
//售票统计按钮响应
void Server::slotbuttonClick()
{
QWidget* window = new QWidget();
window->setWindowTitle(tr("售票统计"));
window->resize(500,500);
list = new QListWidget(window);
QGridLayout *layout = new QGridLayout(window);
layout->addWidget(list);
for(int i = 0;i < evetick.size();++i)
{
list->insertItem(i,evetick.at(i));
}
window->show();
}
//tcpserver.h 创建多线程
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <QWidget>
#include <QObject>
#include <QTcpServer>
#include <QString>
#include <QMap>
#include "server.h"
class Mytcpsocket;
class Tcpserver:public QTcpServer
{
Q_OBJECT
public:
Tcpserver(QWidget* parent = 0);
protected:
void incomingConnection(qintptr socketDescriptor);
signals:
void transsell(QByteArray,QString,QString);//接收tcpsocket传来的信号,并发射给server端,处理数据
private:
QString id;//传送客户端编号
};
#endif // TCPSERVER_H
//tcpserver.cpp
#include "tcpserver.h"
#include "tcpsocket.h"
#include "mythread.h"
Tcpserver::Tcpserver(QWidget* parent):QTcpServer(parent)
{
}
void Tcpserver::incomingConnection(qintptr socketDescriptor)
{
Mytcpsocket* socket = new Mytcpsocket();
socket->tcpSocket = new QTcpSocket();
socket->tcpSocket->setSocketDescriptor(socketDescriptor);
QThread *thread = new QThread();
socket->moveToThread(thread);
connect(socket->tcpSocket,SIGNAL(readyRead()),socket,SLOT(receiveData()),Qt::QueuedConnection);
thread->start();
//将tcpsocket端发送的信号接收过来
connect(socket,SIGNAL(transsell(QByteArray,QString,QString)),this, SIGNAL(transsell(QByteArray,QString,QString)));
}
//tcpsocket.h 不同线程中的socket通信
#ifndef Mytcpsocket_H
#define Mytcpsocket_H
#include <QWidget>
#include <QTcpSocket>
#include <QObject>
class Mytcpsocket:public QObject
{
Q_OBJECT
public:
explicit Mytcpsocket(QObject* parent=0);
signals:
void transsell(QByteArray,QString,QString); //发射给tcpserver端
public slots:
void receiveData(); //在子线程中处理client端传来的信息
public:
QTcpSocket *tcpSocket;
QString byte;
QString str_id;
};
#endif // Mytcpsocket_H
//tcpsocket.cpp
#include "tcpsocket.h"
#include "server.h"
#include <QThread>
#include <QDebug>
#include <QTime>
Mytcpsocket::Mytcpsocket(QObject* parent):QObject(parent)
{
tcpSocket = new QTcpSocket();
}
//将每个客户端的具体情况发送出去
void Mytcpsocket::receiveData()
{
QByteArray receive = tcpSocket->readAll();
QTime time = QTime::currentTime();
QString str = time.toString("H:mm:ss");
int id = (int)QThread::currentThreadId();
str_id = QString::number(id,10);
byte = str_id + tr("客户端") +" " + str +" "+ tr("售出")+ receive ;
emit transsell(receive,byte,str_id);
}
//mainwindow.h 主界面窗口
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QWidget>
#include <QLabel>
#include <QString>
#include "server.h"
#include "client.h"
class Mainwindow: public QWidget
{
Q_OBJECT
public:
Mainwindow(QWidget *parent = 0);
QLabel* _lable;
public slots:
void slotserBtnClick();//服务器登陆按钮
void slotcliBtnClick();//客户端登陆按钮
private:
};
#endif // MAINWINDOW_H
//mainwindow.cpp
#include "mainwindow.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QPushButton>
#include <QFont>
Mainwindow::Mainwindow(QWidget *parent) :
QWidget(parent)
{
setWindowTitle(tr("欢迎进入火车票订票系统"));
setMinimumSize(250,150);
setMaximumSize(250,150);
QFont font("楷体",20);
_lable = new QLabel(this);
_lable->setText("火车票订票系统");
_lable->setFont(font);
QPushButton* serBtn = new QPushButton("服务器登陆");
QPushButton* cliBtn = new QPushButton("客户端登陆");
connect(serBtn, SIGNAL(clicked()), this, SLOT(slotserBtnClick()));
connect(cliBtn, SIGNAL(clicked()), this, SLOT(slotcliBtnClick()));
QGridLayout* glay = new QGridLayout(this);
glay->addWidget(_lable,0,0,2,2);
glay->addWidget(serBtn,2,0,2,1);
glay->addWidget(cliBtn,2,1,2,1);
}
//服务器登陆按钮
void Mainwindow::slotserBtnClick()
{
Server *server = new Server();
server->show();
server->setWindowTitle("服务器");
server->setMinimumSize(500,500);
server->setMaximumSize(500,500);
}
//客户端登录按钮
void Mainwindow::slotcliBtnClick()
{
Client *client = new Client();
client->show();
client->setWindowTitle("客户端");
client->setMinimumSize(500,500);
client->setMaximumSize(500,500);
}
//main.cpp
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Mainwindow* mainwindow = new Mainwindow;
mainwindow->show();
return a.exec();
}
最后
以上就是满意白开水为你收集整理的运用多线程知识写一个火车站售票系统的全部内容,希望文章能够帮你解决运用多线程知识写一个火车站售票系统所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复