网络编程课程设计报告--模拟火车售票退票系统

有缘相会 范文 报告范文
精选回答

网络编程课程设计报告--模拟火车售票退票系统本文简介:Java网络编程报告姓名:蒋怡学号:1107300134题目:模拟火车售票退票系统一、作业要求:模拟火车售票退票系统实现一个服务器为多个客户服务,要求1、服务器用线程池,线程容量为4,座位数为60个,即01-60号座.2、客户通过网络发送请求可以退票可以买票,先来先服务,买票还是退票由随机数决定,退

网络编程课程设计报告--模拟火车售票退票系统本文内容:

Java网络编程报告

姓名:

蒋怡

学号:

1107300134

题目:

模拟火车售票退票系统

一、作业要求:

模拟火车售票退票系统实现一个服务器为多个客户服务,要求

1、

服务器用线程池,线程容量为4,座位数为60个,即01-60号座.

2、

客户通过网络发送请求可以退票可以买票,先来先服务,买票还是退票由随机数决定,退票必须是该用户买过的有效票,先买的票先退。若退票时该用户已没有买到的票,则改为买票。若服务器票已售完,则需等待,先来先服务,哪个客户先来,服务器将先为哪个客户服务。

3、

服务器每次接收一个客户请求需打印该客户的端口号、IP和该用户是买票还是退票,处理该请求之前目前剩余的票所有座号,处理之后剩余的座号也要打印出来,并延迟一个随机处理时间,以模拟对每个客户处理的时间不同。将处理结果发给客户。

4、

客户收到结果后打印到屏幕。

5、

注意资源共享的问题,适当时可用同步代码,不允许用同步方法。注意线程之间的协作。

演示时开放4-5个用户,并演示一次退票无效的情况(即要退的票在服务器中还没有卖出去,要求2是正常情况)

2、

主要设计思路:

1、该程序包括以下几个类:

1)、EchoClient.java

2)、EchoServer.java

3)、Node.java

定义了线性表的一个节点的结构,并对节点进行初始化

4)、LList.java

接口类,包含以下几个方法:

boolean

isEmpty();

//

判断线性表是否为空

int

length();

//

返回线性表长度

T

get(int

i);

//

返回第i(i>0)个元素

void

insert(int

i,T

x);

//

插入x作为第i个元素

void

insert1(T

x);

//按顺序插入一个数到链表中

T

remove(int

i);

//

删除第i个元素并返回被删对象

void

append(T

x);

//

在线性表最后插入x元素

5)、SingleLinkList.java

实现接口LList。

6)、Customer.java

定义了choise,cus_tickets两个属性和choice()方法,其中

choise是一个随机产生的0或1,用来决定客户买票或退票。

cus_list是一个线性表,用来存储客户所买到的所有票。

7)、Tickets.java

定义了number和list两个属性,其中number用来表示服务器售出的票号,list是一个线性表,用来存储剩余火车票。包含了售票票方法sell()和退票方法return_ticket()。

2、

思路及流程图

1)、首先客户端通过调用Customer类的choice()方法,由choice()方法来决定客户是买票还是退票。若choise==1,则客户买票,若choise==0,则客户退票。流程图如下:

客户买票

choice=(int)(Math.random()*2)

choise==1

客户退票票

2)

、若客户买票,则通过输出流将买票信息发送给服务器端。若客户退票,则通过“customer.cus_list.isEmpty()”这个语句判断客户是否有票可退,若客户有票可退,则通过输出流将退票信息及所退票号发送给服务器端;若客户无票可退,则改为买票,通过输出流将信息发送给服务器端。流程图如下:

客户退票

客户拥有的票是否为空

发送退票信息给服务器端

发送买票信息给服务器端

客户买票

发送买票信息给服务器端

3)

、服务器端通过输入流接收客户端的信息,接收信息后,随机产生一个时间,线程休眠,模拟网络延迟。然后判断客户是买票还是退票,若是买票,则调用Tickets类中的sell()方法进行售票处理;若是退票,则调用Tickets类中的return_ticket()方法进行退票处理。流程图如下:

接收客户端的信息

线程休眠一段时间

客户是否买票

tickets.sell()

Tickets.return

_ticket()

4)、若客户是买票的,则通过“list.isEmpty()”判断是否有票可售,若有票可售,则进行售票处理(即将list线性表中的第一个节点删除,表示此票已售出),处理后将信息反馈给客户;客户收到服务器端的信息后,将反馈信息打印输出,同时将所买到的票添加到cus_list线性表的最后。

若无票可售,则线程等待,将线程加入等待队列,当线程被唤醒后,进行售票处理,处理后将信息反馈给客户。客户收到服务器端的信息后,输出反馈的信息,同时,将所买到的票添加到cus_list线性表的最后。

客户收到服务器端反馈信息

打印输出信息

cus_list.append()

是否有票可售

售票处理

售票

线程等待

线程被唤醒后进行售票处理

将线程加入等待队列

将反馈信息发送到客户端

5)

、若客户是退票的,首先判断客户所退的票是否是已售出的票,若不是,则非法退票,退票失败,将反馈信息发送给客户端;若是,则进行退票处理(将所要退的票按大小添加到线性表list中),退票处理后,将反馈信息发送给客户端,然后该线程将已经退了的票从cus_list中删除(即cus_list.remove())。判断是否有线程在等待队列中,若有,则将队列中的第一个线程唤醒,进行售票处理,然后将反馈信息发送给客户端。

退票是否成功

打印输出退票成功信息

cus_list.remove()

输出退票失败信息

客户端收到服务器端的反馈信息

等待队列是否空

退票

该票是否已售出

非法退票,退票失败

退票处理

将所退的票售给第一个等待的线程

将反馈信息发送到客户端

3、

关键代码

for(i=1;i

socketList=new

ArrayList();

//排队序列

public

EchoServer()

throws

IOException

{

serverSocket

=

new

ServerSocket(port);

serverSocket.setReceiveBufferSize(50);

//创建线程池

executorService=

Executors.newFixedThreadPool(

POOL_SIZE);

System.out.println(“服务器启动“);

}

public

void

service()

{

while

(true)

{

Socket

socket=null;

try

{

socket

=

serverSocket.accept();

executorService.execute(new

Handler(socket,socketList));

}catch

(IOException

e)

{

e.printStackTrace();

}

}

}

public

static

void

main(String

args[])throws

IOException

{

new

EchoServer().service();

}

}

class

Handler

implements

Runnable{

private

Socket

socket;

private

Tickets

ticket=new

Tickets();

List

socketList=new

ArrayList();

//排队序列

public

Handler(Socket

socket,List

socketList){

this.socket=socket;

this.socketList=socketList;

}

private

PrintWriter

getWriter(Socket

socket)throws

IOException{

OutputStream

socketOut

=

socket.getOutputStream();

return

new

PrintWriter(socketOut,true);

}

2)

、EchoServer.java

private

BufferedReader

getReader(Socket

socket)throws

IOException{

InputStream

socketIn

=

socket.getInputStream();

return

new

BufferedReader(new

InputStreamReader(socketIn));

}

public

String

echo(String

msg)

{

return

“echo:“+

msg;

}

@SuppressWarnings(“static-access“)

public

void

run(){

try

{

System.out.println(“New

connection

accepted

“+

socket.getInetAddress()

+

“:“+socket.getPort());

BufferedReader

br

=getReader(socket);

PrintWriter

pw

=

getWriter(socket);

String

msg

=

null;

String

cus_number=null;

while

((msg=br.readLine())

!=

null)

{

//

模拟售票的网络延迟

try

{

Thread.sleep((long)

(Math.random()*3000));

//产生一个随机处理时间

}

catch

(InterruptedException

e)

{

e.printStackTrace();

}

if(msg.equals(“buy“))

{

ticket.sell(socketList,socket,pw);

}

else

if(msg.equals(“refund“))

{

ticket.return_ticket(cus_number=br.readLine(),socket,socketList,pw);

}

}

}catch

(IOException

e)

{

e.printStackTrace();

}finally

{

try{

if(socket!=null)socket.close();

}catch

(IOException

e)

{e.printStackTrace();}

}

}

}

public

class

Tickets

{

String

number;//售出票的序号

static

String

tickets[]={“1“,“2“,“3“,“4“,“5“,“6“,“7“,“8“,“9“,“10“,“11“,“12“,“13“,“14“,“15“,“16“,“17“,“18“,“19“,“20“,“21“,“22“,“23“,“24“,“25“,“26“,“27“,“28“,“29“,“30“,“31“,“32“,“33“,“34“,“35“,“36“,“37“,“38“,“39“,“40“,“41“,“42“,“43“,“44“,“45“,“46“,“47“,“48“,“49“,“50“,“51“,“52“,“53“,“54“,“55“,“56“,“57“,“58“,“59“,“60“};

static

SingleLinkList

list

=

new

SingleLinkList(tickets);

//用list链表存储火车票

public

void

sell(List

socketList,Socket

socket,PrintWriter

pw

)

{

synchronized

(list)

{

System.out.println(socket.getPort()+“客户买票“);

System.out.print(“客户买票前剩余火车票为:“);

System.out.println(this.list);

//打印还剩多少张票可卖

if(list.isEmpty())//若无票可售,则将线程加入等待队列

{

System.out.println(“暂时无票!排队中“);

socketList.add(socket);

System.out.println(“客户:“+socket.getInetAddress()+“:“+socket.getPort()+“,队列长度:“+socketList.toArray().length);

System.out.println(“等待队列的第一个客户为:“+socketList.get(0).getPort()+“\n“);

try

{

list.wait();

}

catch

(InterruptedException

e)

{

//

TODO

Auto-generated

catch

block

e.printStackTrace();

}

number=list.remove(1);

System.out.println(“票号:“+number+“被队首:“+socketList.get(0).getPort()+“预定成功\n“);

socketList.remove(0);

pw.println(“客户买到的票的票号为:“+number);//将客户买到票的信息传回给客户

pw.println(number);

//将客户买到的票号传给客户

}

else

{

//若符合条件进行售票

number=list.remove(1);

//每次票号最小的票售出,将已售出的票从火车票链表中移除

System.out.println(“售出票的序号为

“+

number

);//打印售出票的信息

System.out.print(“客户买票后剩余火车票为:“);

System.out.println(list+“\n“);//打印售票后所剩余的火车票

pw.println(“客户买到的票的票号为:“+number);//将客户买到票的信息传回给客户

pw.println(number);

//将客户买到的票号传给客户

}

}

}

3)

、Tickets.java

public

void

return_ticket(String

cus_number,Socket

socket,List

socketList,PrintWriter

pw)

{

//将客户所退的票按顺序添加的票号里面

synchronized

(list)

{

int

i;

for(i=1;i<=list.length();i++)

{

if(list.get(i).equals(cus_number))//判断客户所退的票是否是服务器以售出的票,若不是,则非法退票

{

pw.println(“非法退票!退票失败!“);

System.out.println(“非法退票!退票失败!\n“);

return;

}

}

list.insert1(cus_number);

//将客户退的票按顺序插入到火车票链表中

System.out.println(socket.getPort()+“客户退票,所退票号为:“+cus_number);

System.out.print(“客户退票后剩余火车票为:“);

System.out.println(list+“\n“);

pw.println(“客户退票,所退票号为:“+cus_number);//将客户退票信息传回给客户

if(!socketList.isEmpty())//退票后判断队列中是否有客户在等待买票,若是,则将所退的票买给队列中的第一个客户

{

list.notify();

//唤醒线程

}

}

}

}

4、

程序运行截图

1)、服务器端截图

当票已售完时,客户请求买票就将客户加入一个等待队列,如果有另一个客户来退票,则将所退的票售给等待队列中的第一个客户。

当所

非法退票情况演示:控制客户退票号为20的票,因为20号票还未售出,所以退票失败!

2)、客户端截图

客户请求退票时,客户无票可退,转为买票情况。

5、

实验总结

通过本次实验,掌握了Server

Socket的用法和多线程编程的的原理、还有同步代码块的使用、线程等待和唤醒的使用,在实验过程中遇到了很多不明白的问题,通过找书、与同学讨论都一一解决了。第一次实验的时候,基本上不知道从何处入手,但是通过慢慢的摸索和研究,一步一步地将一个个小问题解决,才能将程序编写出来。在调试过程中,遇到了很多奇奇怪怪的问题,很多时候是因为自己的考虑不够全面和逻辑出来的错误所引起的,在同学的帮助下,把这些问题都一一解决了。

分你半个吻 2022-07-14 02:43:47

相关推荐

蚍蜉撼树是什么意思蚍(蚍蜉撼树是什么意思)

1、蜉蝣树(拼音pfhnsh)是中国成语,蜉蝣树(蜉蝣:一种大蚂蚁;Shake:摇动)比喻力量本来就很弱,但是你想摇动一个很强大的东西,就不能随心所欲了。这个成语一般用作主语、谓语、宾语,属于主谓式,含有贬义。...
展开详情

得意洋洋,反义词(得意洋洋的反义词)

1、得意洋洋的反义词有郁郁寡欢的,有空虚进取的书,有哭天抢地的,有郁郁寡欢的,有失意的,有垂头丧气的,有谦虚谨慎的,有黯然销魂的,有抑郁的。2、“得意”是中国成语,读作:dyyngyng,解释为:得意:明白意图...
展开详情

如法炮制的意思和造句(如法炮制)

1、如法炮制(拼音:rfpozh)是一个成语,起源于西汉的司马迁《史记魏世家》。2、如法炮制(炮制:一种将中药焙炒的方法)是指按照制造方法制造中药;比喻按照现成的方式办事。一般在句子中做谓语、定语、状语。3、出...
展开详情

阳春白雪和下里巴人最初指的是什么(春白雪)

1、杨春白雪。2、杨春白雪,中国的一个成语,发音为yngchnbixu,最初指战国时期楚国比较高雅的歌曲,后来指博大精深的文学艺术。3、战国楚宋玉《对楚王问》:“仲英有歌者,其开头为:《对楚王问》《下里》。全国...
展开详情

依草附木的理解(依草附木的意思)

1、草乌,中国成语,拼音为ycofm,意为鬼神有所依靠,善于造化;比喻依靠他人的力量后,作恶多端;也比喻不能自立,依赖他人。从《巫庙》。2、出自五代和纣王的诗《巫庙》:“天有福报,老人为精灵,循草而沾木,无虚妄...
展开详情

精选推荐更多>

汝只患不能自立,勿患人之不己知翻译

“汝只患不能自立,勿患人之不己知”的翻译是你只需要担心自己能否自立,不要担心别人不懂你。
该句话出自晚张之洞所写的《诫子书》。
节选内容:汝之前途,正亦未有限量,国家正在用武之秋,汝纵患不能自立,勿患人之不己知。志之志之,勿忘勿忘。
译文:你的前程,正可谓不可限量,国家正是在用兵的时候,你只需担心自己不能够成才,不需担心别人不了解自己。记住记住,别忘别忘。
思想:《诫子书》是修身立志的名篇,其文短意长,言简意赅,主旨是劝勉儿子勤学立志,修身养性要从澹泊宁静中下工夫,最忌荒唐险躁。

志存高远的前面是什么

原句为“志当存高远”,前面是“夫”。出自《勉侄书》:“夫志当存高远,慕先贤,绝情欲,弃凝滞,使庶几之志,揭然有所存,恻然有所感。忍屈伸,去细碎,广咨问,除嫌吝;虽有淹留,何损美趣?何患于不济?”
译文:
一个人的志向应当保持高尚远大,仰慕先贤人物,断绝情欲,不凝滞于物,使贤者的志向高高地有所保存,诚恳地有所感受,能屈能伸,抛弃琐碎的东西,广泛地向他人咨询、学习,除去狭隘、悭吝,这样即使未得升迁,又何损于自己美好情趣?何愁理想不能实现?如果意志不坚定,意气不昂扬,徒然随众附和,沉溺于习俗私情,碌碌无为,就将继续伏匿于凡庸人之中,终究不免于卑下的地位。
《勉侄书》是三国时期蜀汉丞相诸葛亮为勉励侄子诸葛恪而作。全文虽87字,字字珠玑,却包含着对侄子诸葛恪的种种期盼,并演变出志存高远一词。

望天门山把什么比作什么

《望天门山》诗中“天门中断楚江开”用了奇妙的比喻,把天门山比作打开的天门。
原文:
天门中断楚江开,碧水东流至此回。
两岸青山相对出,孤帆一片日边来。
译文:
天门山从中间断裂是楚江把它冲开,碧水向东浩然奔流到这里折回。
两岸高耸的青山隔着长江相峙而立,江面上一叶孤舟像从日边驶来。
《望天门山》是唐代大诗人李白于开元十三年(725年)赴江东途中行至天门山时所创作的一首七绝。此诗描写了诗人舟行江中顺流而下远望天门山的情景:前两句用铺叙的方法,描写天门山的雄奇壮观和江水浩荡奔流的气势;后两句描绘出从两岸青山夹缝中望过去的远景,显示了一种动态美。全诗通过对天门山景象的描述,赞美了大自然的神奇壮丽,表达了作者初出巴蜀时乐观豪迈的感情,展示了作者自由洒脱、无拘无束的精神风貌。作品意境开阔,气象雄伟,动静虚实,相映成趣,并能化静为动,化动为静,表现出一种新鲜的意趣。

山居秋暝古诗翻译20个字

《山居秋暝》古诗翻译:空旷的群山沐浴了一场新雨,夜晚降临使人感到已是初秋。皎皎明月从松隙间洒下清光,清清泉水在山石上淙淙淌流。竹林喧响知是洗衣姑娘归来,莲叶轻摇想是上游荡下轻舟。春日的芳菲不妨任随它消歇,秋天的山中王孙自可以久留。
译文:
空山新雨后,天气晚来秋。
明月松间照,清泉石上流。
竹喧归浣女,莲动下渔舟。
随意春芳歇,王孙自可留。
《山居秋暝》是唐代诗人王维的诗作。此诗描绘了秋雨初晴后傍晚时分山村的旖旎风光和山居村民的淳朴风尚,表现了诗人寄情山水田园并对隐居生活怡然自得的满足心情,以自然美来表现人格美和社会美。全诗将空山雨后的秋凉,松间明月的光照,石上清泉的声音以及浣女归来竹林中的喧笑声,渔船穿过荷花的动态,和谐完美地融合在一起,给人一种丰富新鲜的感受。它像一幅清新秀丽的山水画,又像一支恬静优美的抒情乐曲,体现了王维诗中有画的创作特点。
常见热点问答
热点搜索
1-20
21-40
41-60
61-80
81-100
101-120
121-140
141-160
161-180
181-200
作文大全
1-20
21-40
41-60
61-80
81-100
101-120
121-140
141-160
161-180
181-200