题目简介:
在现实世界中有一种数据模型,模拟生产者与消费者模型。如火车票售票系统,将票据的数量录入服务器我们称之为“生产”了若干车票。各地终端会共享这些车票信息去售票。直到车票售票完,则提示无票可卖。
本练习题,在同一台电脑上使用不同的进程(独立运行的应用程序)模拟火车票售票系统。将录入存放火车票的独立运行程序我们称之为服务端。一台电脑只能运行一个实例。其他负责售卖火车票的程序称为客户端。客户端程序,一台电脑可以运行多个实例。客户端程序主要的功能就是消费服务端的火车票。

要求:

  1. 你可以编写带界面的应用程序,也可以编写不带界面的命令行应用程序。
  2. 当客户端关闭时,服务端能够给予提示,当有客户端启动连接时,服务端给予提示。
  3. 当客户段消耗一张车票时,服务端提示信息(信息包含那个客户端,什么时候消耗一张票)。
  4. 假设每个客户端均有一个唯一的编号。
  5. 客户端是模拟买票,可以使用定时器,设置间隔周期,如2秒消耗一张票。
  6. 当客户端无票可卖时(服务器的票已经被消耗完),给予提示。
  7. 当服务器卖完所有的票时给予提示,并统计客户端的卖票情况(每个客户的售票详情,如张数,时间)。

题目难点:
主要考察的是多线程的应用,因为服务器只有一个,不同的客户端购票时间,信息都不相同

开发环境:
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_OBJECTpublic: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();
}



运用多线程知识写一个火车站售票系统相关推荐

  1. 用c++写一个地铁售票系统

    首先,我们需要创建一个地铁售票系统,这个系统应该能够根据乘客的需求提供合适的交通票价:其次,需要提供一个简单的用户界面,方便乘客查询和购买车票:最后,地铁售票系统还需要提供安全的支付系统,以便乘客支付 ...

  2. Java多线程案例:模拟12306火车站售票系统

    Java多线程案例:模拟12306火车站售票系统 该系统一共涉及到3个类: 车票(Ticket) 12306系统(System12306) 售票窗口(Window) 车票类,涉及三个属性: 起始站 终 ...

  3. windows多线程系列001 火车站售票系统模拟程序

    其实我对多线程这一块一直也不是很熟悉,现在正好在项目中需要用到对多线程的优化问题,因此我对多线程的相关知识点进行了学习和总结,在此和大家一起学习和交流.这个系列主要涉及到进程和线程的概念以及利用互斥对 ...

  4. 多线程试验。模拟航班售票系统,实现4个售票窗口发售某班次航班的100张机票,一个售票窗口用一个线程表示。要求不能重复发售。

    五一假期要到了,希望大家都都能开开心心 代码 import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; i ...

  5. 火车站售票系统课程设计

    火车站售票系统课程设计 一.课题内容和要求 设计目标:设计一个火车售票系统,用C语言实现.对该系统的要求如下: (1) 需求描述: 一.系统角色: 1.火车站售票员: 火车站售票员能够使用本系统完成基 ...

  6. 看各路单词APP不顺手 索性自己写一个背单词系统

         作者:王木一      来源:恰好恰好 本文约 3500 字 预计阅读需要 8 分钟 https://github.com/Benature/WordReview 开门见山 先放重点 如果嫌 ...

  7. c语言程序设计火车站售票系统,C语言程序--火车站售票系统程序

    火车站售票系统程序 火车站售票查询系统: #include #include #include #include int shoudsave=0 ; int count1=0,count2=0,mar ...

  8. 看各路单词APP不顺手?索性自己写一个背单词系统

    本文约 3500 字 预计阅读需要 8 分钟 https://github.com/Benature/WordReview 开门见山 先放重点 懒人目录 1. 背单词方法论 / 痛点 2. WordR ...

  9. java 模拟火车站售票系统_模拟售票系统java编程

    模拟售票系统java编程 /* 项目:用多线程设计一个模拟火车站售票大厅的工作情形. 问题描述:火车站有许多售票窗口,有些开放,有些不开放.顾客进入火车站售票厅后,到某个售票窗口排队等候,排到了就办理 ...

最新文章

  1. Python 中的 enumerate 函数
  2. 'utf-8' codec can't decode byte 0xd5 in position 0: invalid continuation byte
  3. Cocos2d-x之Sprite
  4. 六、前端开发-JavaScript DOM
  5. 武汉大学计算机学院的李明,李明副研究员
  6. 【nodejs原理源码赏析(6)】深度剖析cluster模块源码与node.js多进程
  7. java 往excel中写数据库,poi将数据写入excel表格-怎么用java把数据库里的数据写入到excel表中...
  8. php strcmp 比较汉字,php中strcmp() 比较中文是按照什么比较的
  9. 第四周—扒开系统调用的“三层皮”
  10. java伪唤醒,谈谈JDK线程的伪唤醒
  11. 凸优化第四章凸优化问题 4.3线性规划问题
  12. 【原理】 进程调度算法
  13. 呼叫中心系统的解决方案
  14. 如何高效的开展测试工作?
  15. QEMU虚拟机源码分析概论
  16. deepin删除应用程序中图标
  17. 第八课: FTP Server设置与加载
  18. 题解 luoguP2928 【[USACO09HOL]牛的打手Cattle Bruisers】
  19. 04.修改Docker镜像源地址为网易镜像源地址
  20. oracle中取月初,月末,季初,季末及年初,年末时间

热门文章

  1. 微信小程序获取个人头像和昵称,和地图选点功能
  2. 【JokerのZYNQ7020】UART。
  3. Django rest_framework 后端接口开发 开发与用户相关的一组接口 登录注册与用户信息查询修改
  4. 解决打开Chrome网页被2345篡改
  5. Neural Ordinary Differential Equations
  6. 计算机重命名后sql实例名称修改_离水的鱼_新浪博客
  7. Javascript实现表单检验(如注册界面)
  8. 电脑如何关闭445端口
  9. GitHub怎么用?GitHub是什么?新手怎么用GitHub?图文并茂,不看都不行
  10. mysql内存淘汰_从创建索引过程中内存变化来看SQL Server与MySQL的内存淘汰算法