基于java socket的订票程序

基于java socket的订票程序    

    课程作业,用java的socket写了一个控制台版本的机票预订程序,实现了机票的用户的登录,查询,和订票已经历史订票记录查询。

    算是对以前学过的socket网络编程的一次巩固吧,有关socket简单的c/s模型可看我的这篇博客:点击打开链接

    重要的是对等协议的使用,客户端和服务器端消息收发的对称性。

    协议(protocal)都是是自己定义的。

    这里使用了多线程,可以满足多个客户端同时登录,服务器端关于购票业务的同步并发做的不是很完善。

    越做到后面越感觉重要的是业务,不是程序的实现了。

    使用的知识有java+socket+thread+jdbc+mysql。

    业务处理基本都在服务器端,算是一个胖服务器吧,下图差不多可以表示了:


下面是该程序设计的类图:

    

下面是代码:

package pack1;

import java.io.*;
import java.lang.Thread.State;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import com.dao.FlightManageDAO;
import com.dao.LoginDAO;
import com.dao.TicketManageDAO;
import com.model.Flight;
import com.model.Passenger;
import com.model.Ticket;
/**
 * 服务器端
 * @author XWZ
 *
 */
/*常量协议接口*/
interface Protocal {
	int QUERY = 1;			//查询请求
	int PURCHASE = 2;		//购票请求
	int ACCEPT = 3;			//确认
	int ERROR = 4;			//错误
	int EXIT = 5;			//退出请求
	int PAY = 6;			//付款请求
	int LOGIN = 7;			//登录请求
	int QUERYHISTORY = 8;	//查询历史
	int ISLOGIN = 9;		//已登录
}

public class Server {
	static final int PORT = 8888;
	static int m_count = 0;				//当前连接数
	public Server() {}

	public static void main(String[] args) 
	{
		Object object = new Object();
		ServerSocket server_socket = null;
		// 使用线程池,设置最大连接数为100
		ExecutorService threadPool = Executors.newFixedThreadPool(100);
		try 
		{
			server_socket = new ServerSocket(PORT);
			System.out.println("Server is running");
			while (true) 
			{
				Socket client_socket = server_socket.accept();
				m_count = ((ThreadPoolExecutor)threadPool).getActiveCount();
				System.out.println("当前连接数:" + (m_count+1));
				Thread thread = new Thread(new ProcessThread(client_socket,object));
				threadPool.submit(thread);
			}
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		}
		threadPool.shutdown();
	}
}

/*服务器线程类*/
class ProcessThread implements Runnable,Protocal{
	
	Socket client;				//当前连接客户端
	BookTicket bt;				//业务处理对象

	ProcessThread() {}

	/*构造函数*/
	ProcessThread(Socket client,Object object) 
	{
		this.client = client;
		this.bt = new BookTicket(object);
	}
	
	/* 线程函数 */
	public void run() 
	{
			try 
			{
				System.out.println("get connect from:" + client.getInetAddress() + ",port:" + client.getPort());
				while (onReceive())
					;
				System.out.println("客户端:" + client.getInetAddress() + ",port:" + client.getPort() + "退出");
				client.close();
			}
			catch (Exception e) 
			{
				e.printStackTrace();
			}
	}

	//协议解析函数
	public boolean onReceive() {
		int flag = 0;				//用户监测客户端是否断开连接,-1为断开
		try {
			//处理客户端异常断开
			client.sendUrgentData(0); 
			
			ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(client.getInputStream()));
			Integer nChoice = (Integer)is.readObject();
			ObjectOutputStream os = new ObjectOutputStream(client.getOutputStream());
	
			if(nChoice != null) 
			{
				switch (nChoice) 
				{
					case QUERY:
						bt.queryFlight(is,os);
						break;
					case PURCHASE:
						bt.bookTickt(is,os);
						break;
					case LOGIN:
						bt.login(is,os);
						break;
					case QUERYHISTORY:
						bt.queryHistory(is,os);
						break;
					case EXIT:
						bt.logout();
						flag = -1;
						break;
					default:
						flag = -1;
						break;
				}//switch
			}//if
		}//try
		catch (Exception e) 
		{
			flag = -1;
			bt.logout();
			e.printStackTrace();
		}
		
		if((flag < 0) || (client.isClosed()))
		{
			return false;
		}
		return true;
	}
}

/*订票业务处理类*/
class BookTicket implements Protocal{
	FlightManageDAO fdao;				//数据库访问对象
	TicketManageDAO tdao;				//购票数据库访问对象
	LoginDAO ldao;						//登录数据库访问对象
	List<Flight> fList = null;			//航班列表
	Passenger passenger = null;			//当前用户
	
	static int i = 10;                              //剩余票数,用来模拟并发
	Object object = null;				//共用锁对象		
	
	/*构造函数*/
	BookTicket(Object object) 
	{
		this.fdao = new FlightManageDAO();
		this.tdao = new TicketManageDAO();
		this.ldao = new LoginDAO();
		this.object = object;
	}

	/*机票查询函数*/
	public void queryFlight(ObjectInputStream is,ObjectOutputStream os) throws ClassNotFoundException, IOException 
	{
   		Object obj1 = is.readObject();
		Object obj2 = is.readObject();
		//Object obj3 = is.readObject();
		
		if (!(obj1 == null) && !(obj2 == null)) 
		{
			String start = (String) obj1;
			String arrival = (String) obj2;
			//String date = (String) obj3;
			fList = fdao.queryFilght(start, arrival);
			os.writeObject(fList);
		}
	}
	
	/*机票预订函数*/
	public synchronized void bookTickt(ObjectInputStream is,ObjectOutputStream os) throws IOException, ClassNotFoundException 
	{
		Integer nChoice = (Integer)is.readObject();		//获取客户选择的航班
		if(nChoice != null)
		{
			if(i>0)                                        //有余票
			{
				if((fList.size()>nChoice) && (nChoice>=0))
				{
					os.writeObject(new Integer(PAY));
					{
						//处理支付环节
					}
					
					//生成订单
					if((this.passenger != null))
					{
						Flight flight = fList.get(nChoice);
						Ticket ticket = new Ticket(flight, passenger, i--);
						int result = tdao.saveTicketInfo(ticket);
						if(result > 0)
							os.writeObject(ticket);
						else
							os.writeObject(ERROR);
					}
				} 
			}
			else
			{
				os.writeObject(new Integer(ERROR));
			}
		}//if
	}
	
	/*查询历史购票记录*/
	public void queryHistory(ObjectInputStream is,ObjectOutputStream os) throws IOException
	{
		List<Ticket> tList =  tdao.queryHistoryTicket(passenger.getUsername());
		os.writeObject(tList);
	}
	
	/*登录函数*/
	public void login(ObjectInputStream is,ObjectOutputStream os) throws ClassNotFoundException, IOException
	{
		String username = (String)is.readObject();
		String password = (String)is.readObject();
		if((username != null) && (password != null))
		{
			Passenger p = ldao.checkPermission(username, password);
			if(p != null)
			{
				this.passenger = p;
				if(!p.isLogin())
				{
					os.writeObject(ACCEPT);
				}
				else 
				{	//已登录
					os.writeObject(ISLOGIN);
				}
			}
			else
			{		//无此用户
				os.writeObject(ERROR);
			}
		}
		else
		{			//用户名或密码为空
			os.writeObject(ERROR);
		}
	}
	
	public void logout()
	{
		ldao.logOut(passenger);
	}
}

package com.client;

import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import com.model.Flight;
import com.model.Ticket;
/**
 * 客户端
 * @author XWZ
 *
 */
/*常量协议接口*/
interface Protocal {
	int QUERY = 1;
	int PURCHASE = 2;
	int ACCEPT = 3;
	int ERROR = 4;
	int EXIT = 5;
	int PAY = 6;
	int LOGIN = 7;
	int QUERYHISTORY = 8;
	int ISLOGIN = 9;
}

public class Client implements Protocal{
	static final int PORT = 8888;
	static final String HOST = "127.0.0.1";
	int count = 0;
	Socket socket = null;

	public Client() 
	{
		try 
		{
			socket = new Socket();
			socket.connect(new InetSocketAddress(HOST, PORT));
		} 
		catch (IOException e) 
		{
			//e.printStackTrace();
		}
	}

	public static void main(String[] args) 
	{
		Client client = new Client();
		if(client.socket.isConnected())
		{
			while(!client.login())
				;
			
			while (client.menu())
				;
			System.out.println("GoodBye");
		}
		else
		{
			System.out.println("503 Service Unavailable,Server error..");
		}
		try 
		{
			client.socket.close();
		} 
		catch (Exception e) {}
	}

	public boolean menu() 
	{
		if (count < 1) 
		{
			System.out.println("-----------蓝天机票销售系统主界面----------");
			System.out.println("1、机票查询");
			System.out.println("2、查询历史乘机记录");
			System.out.println("3、退出系统");
			count++;
		}
		System.out.println("请输入操作选项:");

		boolean flag = true;
		Scanner sc = new Scanner(System.in);
		Integer nChoice = sc.nextInt();
		switch (nChoice) {
		case 1:
			queryTicket(socket);
			break;
		case 2:
			queryHistory(socket);
			break;
		case 3:
			flag = false;
			exit(socket);
			break;
		default:
			System.out.println("没有此选项,请重新输入!");
			break;
		}
		if (!flag)
			return false;
		return true;
	}

	/* 机票查询 */
	public void queryTicket(Socket socket) 
	{
		String start = null;
		String arrival = null;
		int flag = -1;
		try {
		
			ObjectOutputStream os1 = new ObjectOutputStream(socket.getOutputStream());
			os1.writeObject(new Integer(QUERY));

			 Scanner sc = new Scanner(System.in);
			while(flag<0)
			{
				System.out.println("请输入出发城市:");
				start = sc.nextLine();
				System.out.println("请输入到达城市:");
				arrival = sc.nextLine();
				if(start.trim().equals("") || arrival.trim().equals(""))
				{
					System.out.println("出发地或目的地不能够为空!请重新输入:");
				}
				else
				{
					flag = 1;
				}
			}
			System.out.println("出发地:"+start +" 目的地:"+arrival);
			os1.writeObject(start);
			os1.flush();
			os1.writeObject(arrival);
			
			ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
			Object obj = is.readObject();
			if (obj != null) 
			{
				@SuppressWarnings("unchecked")
				List<Flight> fList = (ArrayList<Flight>) obj;
				if (fList.size() < 1) 
				{
					System.out.println("无符合条件的航班!");
				} 
				else 
				{
					System.out.println("航班序号	航班号	初始地	目的地	日期		起飞时间		到达时间");
					for (int i = 0; i < fList.size(); i++) 
					{
						Flight flight = fList.get(i);
						System.out.println((i + 1) + "	" 
												+flight.getId() + "	" 
												+flight.getFrom() + "	"
												+flight.getTo() + "	" 
												+flight.getDate() + "	" 
												+flight.getStartTime()+ "		" 
												+flight.getArriveTime());
					}

					System.out.println("请选择航班序号或返回(0为返回)");
					Integer nChoice = sc.nextInt();
					if (nChoice != 0) 
					{
						while ((nChoice < 0) || (nChoice > fList.size())) 
						{
							System.out.println("输入错误,请重新输入!");
							nChoice = sc.nextInt();
						}
						// 航班序号输入正确, 调用购票函数
						bookTicket(socket, nChoice-1);
					} 
					else 
					{
						// 完成该次查询,返回主菜单
					}
				}
			} 
			else 
			{
				// System.out.println("数据传输出错");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 机票预订
	public void bookTicket(Socket socket, Integer nChoice) 
	{
		try {
			ObjectOutputStream os;
			os = new ObjectOutputStream(socket.getOutputStream());
			os.writeObject(new Integer(PURCHASE));
			os.writeObject(nChoice);
			
			ObjectInputStream is = new ObjectInputStream(socket.getInputStream());
			Integer result = (Integer) is.readObject();
			if (result == PAY)
			{
				//付款
				System.out.println("请付款:");
				Scanner sc = new Scanner(System.in);
				sc.nextLine();
				
				//接收订单信息
				
				Object obj = is.readObject();
				
				if(obj instanceof Ticket)
				{
					Ticket ticket = (Ticket)obj;
					if(ticket != null)
					{
						System.out.println("恭喜您,订票成功!机票信息为");
						System.out.println("订单号		航班号		出发日期		始发地	目的地	起飞时间	抵达时

间	乘机人	座位号	预订状态");
						System.out.print(ticket.getOrderId());
						System.out.print("	"+ticket.getFlight().getId());
						System.out.print("		"+ticket.getFlight().getDate());
						System.out.print("	"+ticket.getFlight().getFrom());
						System.out.print("	"+ticket.getFlight().getTo());
						System.out.print("	"+ticket.getFlight().getStartTime());
						System.out.print("	"+ticket.getFlight().getArriveTime());
						System.out.print("	"+ticket.getPassenger().getUsername());
						System.out.print("	"+ticket.getSeat());
						System.out.println("	"+ticket.getState());
					}
				}
				else
				{
					System.out.println("系统繁忙!订票失败!");
				}
			}//if
		} //try
		catch (Exception e) 
		{
			e.printStackTrace();
		}
	}

	public void userInfoManage(Socket socket) {
	}
	
	/*查询历史订票记录*/
	public void queryHistory(Socket socket) 
	{
		try {
			ObjectOutputStream os;
			os = new ObjectOutputStream(socket.getOutputStream());
			os.writeObject(new Integer(QUERYHISTORY));
			
			ObjectInputStream is = new ObjectInputStream(socket.getInputStream());
			@SuppressWarnings("unchecked")
			List<Ticket> tList = (ArrayList<Ticket>) is.readObject();
			if (tList.size()>0)
			{
					System.out.println("订单号		航班号		出发日期		始发地	目的地	起飞时间	抵达时间	

乘机人	座位号	预订状态");
					for(int i = 0; i < tList.size(); i++)
					{
						Ticket ticket = tList.get(i);
						System.out.print(ticket.getOrderId());
						System.out.print("	"+ticket.getFlight().getId());
						System.out.print("		"+ticket.getFlight().getDate());
						System.out.print("	"+ticket.getFlight().getFrom());
						System.out.print("	"+ticket.getFlight().getTo());
						System.out.print("	"+ticket.getFlight().getStartTime());
						System.out.print("	"+ticket.getFlight().getArriveTime());
						System.out.print("	"+ticket.getPassenger().getUsername());
						System.out.print("	"+ticket.getSeat());
						System.out.println("	"+ticket.getState());
					}
			}
			else
			{
				System.out.println("您暂无订票记录!");
			}
		} 
		catch (Exception e) 
		{
			e.printStackTrace();
		}
	}

	/*退出函数,与服务器断开连接*/
	public void exit(Socket socket) 
	{
		ObjectOutputStream os = null;
		try {
			os = new ObjectOutputStream(socket.getOutputStream());
			os.writeObject(new Integer(EXIT));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/*登录函数*/
	public boolean login()
	{
		boolean result = false;
		int flag = -1;
		String username = null;
		String password = null;
		Scanner sc = new Scanner(System.in);
		System.out.println("-----------蓝天机票销售系统登录界面----------");
		while(flag<0)
		{
			System.out.print("请输入用户名:");
			username = sc.nextLine();
			System.out.print("请输入密码:");
			password = sc.nextLine();
			if(username.trim().equals("") || password.trim().equals(""))
			{
				System.out.println("用户名或密码为空!请重新输入用户名和密码:");
			}
			else
			{
				flag = 1;
			}
		}
		try {
			ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
			os.writeObject(new Integer(LOGIN));
			os.writeObject(username);
			os.writeObject(password);
			
			ObjectInputStream is = new ObjectInputStream(socket.getInputStream());
			Integer nResult = (Integer)is.readObject();
			if(nResult != null)
			{
				if(nResult == ACCEPT)
				{
					result = true;
					System.out.println("登录成功! 跳转至主界面...");
				}
				else if (nResult == ISLOGIN)
				{
					System.out.println("您已登录,不能重新登录!");
				}
				else
				{
					System.out.println("用户名或密码错误!请重新登录");
				}
			}
			
		} 
		catch (Exception e) 
		{
			e.printStackTrace();
		}
		return result;
	}
}

完整的代码可以到这里下载:点击打开链接

附加聊天室服务器端的实现:




网上订票系统 用到的技术为:javabean-servlet-jsp sql server 2000 数据库文件在WebRoot的DB文件中! 本系统实现了会员注册,会员登录,密码修改,以及会员信息的修改! 初步实现了在线订购,订单查询,班次查询以及系统管理--对火车信息的添加等。 操作过程: 首先,应导入到myeclipse中,将该系统发布到tomcat中,并启动tomcat! 接着在360浏览器中输入http://localhost:8080/bookonline/login.jsp 管理员的帐号为:guanliyuan 密码为:123456789 用户帐号为:987654321 密码为:987654321 当然可以在登录界面中点击注册链接,跳转到注册页面中进行注册(注:只能注册用户的,没有管理员注册!这是该系统中的一个问题)。 登录进去后进入主界面main.jsp中。在该界面中,可以点击修改用户信息,密码等链接,管理员还可以点击添加火车信息的链接。当然还可以查看火车信息。(注:只有在查询后,才能进行订票)。 注: 用到的页面 login.jsp——登录界面,可以链接到注册用户的界面。用admin字段来标识是否为管理员。其中有一个用户为987654321密码为987654321,另一个为管理员guanliyuan密码为123456789 register.jsp——用户注册页面,默认的所有注册方式为用户,即所有的用户admin为0。而管理员事先设置好了,即admin为1。 registerfailed.jsp registersuccess.jsp——为注册成功或失败时用到的页面 main.jsp——为系统主页面,在这里可以链接到订票,查询,修改信息,修改密码,管理员添加火车信息等。该页面用到了专题咨询里面的主框架结构,和部分代码。 queryfailed.jsp——当查询失败时所连接到的界面 addtrain.jsp——管理员添加火车信息时的页面 adderror.jsp——用户点击添加火车信息时产生的错误界面 showticket.jsp——显示火车票信息,此时可以进行订票。 bookfailes.jsp booksuccess.jsp——订票成功或失败时所链接的界面。 view.jsp——浏览火车票信息。 modifyinfo.jsp——修改用户信息,在这里不可能更改密码,以及权限。 passwordmodify.jsp——修改密码!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值