java使用socket模拟咖啡馆场景,客户与服务器多线程交互场景
任务的目标是使用客户机 - 服务器架构构建一个“虚拟咖啡馆”系统每个客户端应用程序将扮演 Customer 谁想点茶或咖啡。服务器应用程序将扮演咖啡馆虚拟的角色 Barista 负责处理订单,准备茶和啡,并将订单交还给客户
- 启动Socket服务
public class Customer {private static Socket socketClient;private static boolean connectionState = false;private static ObjectOutputStream oos;private static ObjectInputStream ois;public static void main(String[] args) {//Create a client objecttry {Socket s = new Socket("127.0.0.1", 8888);ClientSend sendclient = new ClientSend(s);sendclient.start();// 创建读取字符流BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));while(true){String serverimg = br.readLine();System.out.println(serverimg);}} catch (IOException e) {System.out.println("The server is offline.");}}}
- 发送客户端
public class ClientSend extends Thread {Socket ss;PrintWriter pw;Scanner sc = new Scanner(System.in);public ClientSend(Socket s) {this.ss = s;try {this.pw = new PrintWriter(s.getOutputStream());} catch (IOException e) {e.printStackTrace();}}@Overridepublic void run() {try {System.out.println("Please enter your name :");String name = sc.nextLine();pw.println("name " + name);pw.flush();while (true){System.out.println("Please enter the command :");String input = sc.nextLine();pw.println(input);pw.flush();if ("exit".equals(input)) {System.out.println("thank you");ss.close();}System.out.println("Please enter the command :");String inpu1 = sc.nextLine();pw.println(inpu1);pw.flush();if ("exit".equals(inpu1)) {System.out.println("thank you");ss.close();}System.out.println("Please enter the command :");String inpu2 = sc.nextLine();pw.println(inpu2);pw.flush();if ("exit".equals(inpu2)) {System.out.println("thank you");ss.close();}System.out.println("Please enter the command :");String inpu3 = sc.nextLine();pw.println(inpu3);pw.flush();if ("exit".equals(inpu3)) {System.out.println("thank you");ss.close();}}} catch (Exception e) {System.out.println("The server is offline.");} finally {if (pw != null) {pw.close();}if (ss != null) {try {ss.close();} catch (IOException e) {System.out.println("");}}}}
}
- 咖啡制造区
public class MakeCoffeeArea extends Thread {/*** 制作coffee** @param*/@Overridepublic void run() {while (true){//获取未制作的制作coffee开始制作List<Coffee> coffeeList = WaitingArea.getCoffeeList();if (!OrderTool.isEmpty(coffeeList)) {if (coffeeList.size() == 1) {//制作前更新咖啡的状态和订单状态for (int i = 0; i < 1; i++) {Coffee coffee = coffeeList.get(i);coffee.setState(1);Order order = OrderTool.getOrderTool().getOneOrder(coffee.getOrderId());order.setState("1");OrderTool.getOrderTool().updateCoffeeState(order, coffee);}System.out.println("开始制作coffee"+OrderTool.getOrderTool().toOrderList());OrderTool.writeJson("开始制作coffee"+OrderTool.getOrderTool().toOrderList());try {Thread.sleep(45000);} catch (InterruptedException e) {System.out.println(e);}for (int i = 0; i < 1; i++) {Coffee coffee = coffeeList.get(i);coffee.setState(2);Order order = OrderTool.getOrderTool().getOneOrder(coffee.getOrderId());OrderTool.getOrderTool().updateCoffeeState(order, coffee);}} else {for (int i = 0; i < 2; i++) {Coffee coffee = coffeeList.get(i);coffee.setState(1);Order order = OrderTool.getOrderTool().getOneOrder(coffee.getOrderId());order.setState("1");OrderTool.getOrderTool().updateCoffeeState(order, coffee);}System.out.println("开始制作coffee"+OrderTool.getOrderTool().toOrderList());OrderTool.writeJson("开始制作coffee"+OrderTool.getOrderTool().toOrderList());try {Thread.sleep(45000);} catch (InterruptedException e) {e.printStackTrace();}for (int i = 0; i < 2; i++) {Coffee coffee = coffeeList.get(i);coffee.setState(2);Order order = OrderTool.getOrderTool().getOneOrder(coffee.getOrderId());OrderTool.getOrderTool().updateCoffeeState(order, coffee);}}}else {try {Thread.sleep(20000);} catch (InterruptedException e) {e.printStackTrace();}}OrderTool.writeJson("制作列表coffee"+OrderTool.getOrderTool().toOrderList());System.out.println("制作列表coffee"+OrderTool.getOrderTool().toOrderList());}}
}
- 茶制作区
public class MakeTeaArea extends Thread {@Overridepublic void run() {while (true){//获取未制作的茶开始制作List<Tea> teaList = WaitingArea.getTeasList();if (!OrderTool.isEmpty(teaList)){if (teaList.size()==1){for (int i=0;i<1;i++){Tea tea = teaList.get(i);tea.setState(1);Order order = OrderTool.getOrderTool().getOneOrder(tea.getOrderId());order.setState("1");OrderTool.getOrderTool().updateTeaState(order,tea);}System.out.println("开始制作茶"+OrderTool.getOrderTool().toOrderList());try {Thread.sleep(30000);} catch (InterruptedException e) {e.printStackTrace();}for (int i=0;i<1;i++){Tea tea = teaList.get(i);tea.setState(2);Order order = OrderTool.getOrderTool().getOneOrder(tea.getOrderId());OrderTool.getOrderTool().updateTeaState(order,tea);}}else {for (int i=0;i<2;i++){Tea tea = teaList.get(i);tea.setState(1);Order order = OrderTool.getOrderTool().getOneOrder(tea.getOrderId());OrderTool.getOrderTool().updateTeaState(order,tea);}System.out.println("开始制作茶"+OrderTool.getOrderTool().toOrderList());try {Thread.sleep(30000);} catch (InterruptedException e) {e.printStackTrace();}for (int i=0;i<2;i++){Tea tea = teaList.get(i);tea.setState(2);Order order = OrderTool.getOrderTool().getOneOrder(tea.getOrderId());order.setState("1");OrderTool.getOrderTool().updateTeaState(order,tea);}}}else {try {Thread.sleep(20000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("制作茶列表"+OrderTool.getOrderTool().toOrderList());}}}
- 托盘区
public class TrayArea extends Thread{@Overridepublic void run() {while (true){try {Thread.sleep(20000);} catch (InterruptedException e) {e.printStackTrace();}List<Order> orders = OrderTool.getOrderTool().getByStateOrderList("1");System.out.println("订单状态为制作中"+OrderTool.toJson(orders));//OrderTool.writeJson("订单状态为制作中"+OrderTool.toJson(orders));if (!OrderTool.isEmpty(orders)){orders.forEach(order -> {if (!OrderTool.isEmpty(order.getTeas())&&OrderTool.isEmpty(order.getCoffees())){boolean teaOk= order.getTeas().stream().allMatch(tea -> "2".equals(String.valueOf(tea.getState())));if (teaOk){order.setState("2");}}if (!OrderTool.isEmpty(order.getCoffees())&&OrderTool.isEmpty(order.getTeas())){boolean coffeeOk= order.getCoffees().stream().allMatch(coffee -> "2".equals(String.valueOf(coffee.getState())));if (coffeeOk){order.setState("2");}}if (!OrderTool.isEmpty(order.getCoffees())&&!OrderTool.isEmpty(order.getTeas())){boolean coffeeOk= order.getCoffees().stream().allMatch(coffee -> "2".equals(String.valueOf(coffee.getState())));boolean teaOk= order.getTeas().stream().allMatch(tea -> "2".equals(String.valueOf(tea.getState())));if (coffeeOk&&teaOk){order.setState("2");}}});List<Order> orderList =OrderTool.getOrderTool().getByStateOrderList("2");orderList.stream().forEach(order -> {if (!OrderTool.isEmpty(order.getTeas())&&OrderTool.isEmpty(order.getCoffees())){ThreadQueue.getThreadQueue().sendAll("order delivered to "+order.getName()+" ("+order.getTeas().size()+" teas)");}if (!OrderTool.isEmpty(order.getCoffees())&&OrderTool.isEmpty(order.getTeas())){ThreadQueue.getThreadQueue().sendAll("order delivered to "+order.getName()+" ("+order.getCoffees().size()+" coffee)");}if (!OrderTool.isEmpty(order.getCoffees())&&!OrderTool.isEmpty(order.getTeas())){ThreadQueue.getThreadQueue().sendAll("order delivered to "+order.getName()+" ("+order.getTeas().size()+" teas and "+order.getCoffees().size()+" coffee)");}try {Thread.sleep(20000);} catch (InterruptedException e) {e.printStackTrace();}OrderTool.getOrderTool().getOrderList().remove(order);});}else {try {Thread.sleep(20000);} catch (InterruptedException e) {e.printStackTrace();}}}}}
- 等候区
public class WaitingArea {/*** 获取需要制作咖啡* @return*/public static List<Coffee> getCoffeeList(){List<Coffee> coffeeList = new ArrayList<>();List<Order> orders = OrderTool.getOrderTool().getOrderList();if (!OrderTool.isEmpty(orders)){orders.stream().forEach(order -> {order.setState("1");if (!OrderTool.isEmpty(order.getCoffees())){order.getCoffees().stream().forEach(coffee -> {//未制作if (coffee.getState()==0){coffeeList.add(coffee);}});}});}return coffeeList;}/*** 获取需要制作茶* @return*/public static List<Tea> getTeasList(){List<Tea> teaList = new ArrayList<>();List<Order> orders = OrderTool.getOrderTool().getOrderList();if (!OrderTool.isEmpty(orders)){orders.stream().forEach(order -> {order.setState("1");if (!OrderTool.isEmpty(order.getTeas())){order.getTeas().stream().forEach(tea -> {//未制作if (tea.getState()==0){teaList.add(tea);}});}});}return teaList;}
}
- 线程队列
public class ThreadQueue {//创建单例模型private ThreadQueue() {}private static final ThreadQueue si = new ThreadQueue();public static ThreadQueue getThreadQueue() {return si;}//创建一个存储 线程 和端口 的Hashtable集合Hashtable<SocketListeningAndSend, Socket> ht = new Hashtable<SocketListeningAndSend, Socket>();public void add(SocketListeningAndSend ri, Socket nowsocket) {//将每一个线程 和 对应的socket 加入集合中ht.put(ri, nowsocket);}//线程清除public void remove(SocketListeningAndSend ri, Socket nowsocket) {ht.remove(ri, nowsocket);}//表示当前的线程给集合中的 非自己 的线程发送的信息public void sendAll( String img) {//遍历集合for (Map.Entry<SocketListeningAndSend, Socket> entry : ht.entrySet()) {SocketListeningAndSend nowRi = entry.getKey();//传递 不一致客户端线程,并且发送当前 线程的socket信息nowRi.firstSend(img, ht.get(nowRi));}}
}
public class SocketListeningAndSend extends Thread {Socket socket;String port;public SocketListeningAndSend(Socket s, String port) {this.socket = s;this.port = port;}public void firstSend(String str, Socket nowsocket) {try {socket.getOutputStream().write((str + "\r\n").getBytes());} catch (IOException e) {OrderTool.writeJson("The client is disconnected. Procedure");//需要写一个清除当前该客户端的方法ThreadQueue.getThreadQueue().remove(this, socket);OrderTool.writeJson(socket.getPort() + "The client is disconnected. Procedure");Order order = OrderTool.getOrderTool().getOneOrder(String.valueOf(socket.getPort()));OrderTool.getOrderTool().getOrderList().remove(order);}}@Overridepublic void run() {OrderTool orderTool = OrderTool.getOrderTool();try {BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String line = null;//接收客户端的数据while ((line = br.readLine()) != null) {String[] s = line.split(" ");for (int i = 0; i < s.length; i++) {System.out.println(s[i] + "--" + i);}System.out.println(OrderTool.toJson(s));switch (s[0]) {case "name":if (!isBlank(s[2])) {int id = socket.getPort();orderTool.createOrder(String.valueOf(id), s[2], 0, 0);} else {firstSend("You typed the name in the wrong format", socket);}break;case "order":int id = socket.getPort();if (s.length == 3) {if ("tea".equals(s[2])) {orderTool.createOrder(String.valueOf(id), null, Integer.valueOf(s[1]), 0);}if ("coffee".equals(s[2])) {orderTool.createOrder(String.valueOf(id), null, 0, Integer.valueOf(s[1]));}if ("status".equals(s[2])) {Order order = orderTool.getOneOrder(String.valueOf(id));int coffeeState0 = orderTool.getByStateCoffeeList(order, "0");int teaState0 = orderTool.getByStateTeaList(order, "0");if (coffeeState0 > 0 && teaState0 > 0) {firstSend(coffeeState0 + " coffee and " + teaState0 + " teas in waiting area", socket);} else if (coffeeState0 > 0) {firstSend(coffeeState0 + " coffee in waiting area", socket);} else if (teaState0 > 0) {firstSend(teaState0 + " teas in waiting area", socket);}int coffeeState1 = orderTool.getByStateCoffeeList(order, "1");int teaState1 = orderTool.getByStateTeaList(order, "1");if (coffeeState1 > 0 && teaState1 > 0) {firstSend(coffeeState1 + " coffee and " + teaState1 + " teas currently being prepared", socket);} else if (coffeeState1 > 0) {firstSend(coffeeState1 + " coffee in currently being prepared", socket);} else if (teaState1 > 0) {firstSend(teaState1 + " teas in currently being prepared", socket);}int coffeeState2 = orderTool.getByStateCoffeeList(order, "2");int teaState2 = orderTool.getByStateTeaList(order, "2");if (coffeeState2 > 0 && teaState2 > 0) {firstSend(coffeeState2 + " coffee and " + teaState2 + " teas currently in the tra", socket);} else if (coffeeState2 > 0) {firstSend(coffeeState2 + " coffee in currently in the tra", socket);} else if (teaState2 > 0) {firstSend(teaState2 + " teas in currently in the tra", socket);}if (coffeeState0 == 0 && teaState0 == 0 && coffeeState1 == 0 && teaState1 == 0 && coffeeState2 == 0 && teaState2 == 0) {firstSend("No order was found for " + order.getName(), socket);}}} else if (s.length == 6) {if (("tea".equals(s[2]) || "teas".equals(s[2])) && ("coffee".equals(s[5]) || "coffees".equals(s[5]))) {orderTool.createOrder(String.valueOf(id), null, Integer.valueOf(s[1]), Integer.valueOf(s[4]));}if (("coffee".equals(s[2]) || "coffees".equals(s[2])) && ("tea".equals(s[5]) || "teas".equals(s[5]))) {orderTool.createOrder(String.valueOf(id), null, Integer.valueOf(s[4]), Integer.valueOf(s[1]));}} else {firstSend("Please enter the correct command", socket);return;}if (!"status".equals(s[2])) {Order order = orderTool.createOrder(String.valueOf(id), null, 0, 0);String str = "order received for ";if (!isBlank(order.getName())) {str += order.getName();}if (!OrderTool.isEmpty(order.getTeas()) && OrderTool.isEmpty(order.getCoffees())) {str += "(" + order.getTeas().size() + " teas}";}if (!OrderTool.isEmpty(order.getCoffees()) && OrderTool.isEmpty(order.getTeas())) {str += "(" + order.getCoffees().size() + " coffees}";}if (!OrderTool.isEmpty(order.getCoffees()) && !OrderTool.isEmpty(order.getTeas())) {str += "(" + order.getTeas().size() + " teas and " + order.getCoffees().size() + " coffees}";}firstSend(str, socket);}break;default:firstSend("Error of instruction", socket);break;}}} catch (IOException e) {System.out.println(socket.getPort() + "The client is disconnected. Procedure");OrderTool.writeJson(socket.getPort() + "The client is disconnected. Procedure");}}public static boolean isBlank(final CharSequence cs) {int strLen;if (cs == null || (strLen = cs.length()) == 0) {return true;}for (int i = 0; i < strLen; i++) {if (Character.isWhitespace(cs.charAt(i)) == false) {return false;}}return true;}
}
public class ServerAccept extends Thread{@Overridepublic void run() {try {System.out.println("Wait for the client to connect");ServerSocket ss = new ServerSocket(8888);//由于可能当有多个客户端连接时,accept方法就会产生多个Socket对象,需加一个while循环监听来自客户端的连接while(true){//侦听套接字的连接,accept是一个阻塞的方法,会阻塞当前的线程Socket s = ss.accept();//建立连接,表示serverSocket在监听,如果监听到有客户端连接则会调用accept方法,然后返回一个Socket,最后建立连接SocketListeningAndSend rs = new SocketListeningAndSend(s,String.valueOf(s.getPort()));//会产生多条线程rs.start();ThreadQueue.getThreadQueue().add(rs,s);//只有一个实例MakeTeaArea makeTeaArea = new MakeTeaArea();makeTeaArea.start();MakeCoffeeArea makeCoffeeArea =new MakeCoffeeArea();makeCoffeeArea.start();TrayArea trayArea = new TrayArea();trayArea.start();}} catch (IOException e ) {System.out.println(e);}}
}
public class OrderTool {private static final OrderTool ORDER_TOOL = new OrderTool();/*** 获取所有订单*/private List<Order> orderList;private OrderTool(){}static {ORDER_TOOL.orderList=new ArrayList<>();}public List<Order> getOrderList(){return this.orderList;}/*** 获取不同* @param state 0 等待区 1 制作区 2 等候 3完成* @return*/public List<Order> getByStateOrderList(String state){List<Order> orders= ORDER_TOOL.getOrderList();List<Order> stateOrderList =new ArrayList<>();for (int i =0;i<orders.size();i++){Order order1 = orderList.get(i);if (state.equals(order1.getState())){stateOrderList.add(order1);}}return stateOrderList;}/*** 获取不同状态 Coffee 数量* @param order* @param state* @return*/public int getByStateCoffeeList(Order order,String state){List<Coffee> coffees =new ArrayList<>();if (!isEmpty(order.getCoffees())){order.getCoffees().forEach(coffee -> {if (String.valueOf(coffee.getState()).equals(state)){coffees.add(coffee);}});}return coffees.size();}/*** 获取不同状态 Tea 数量* @param order* @param state* @return*/public int getByStateTeaList(Order order,String state){List<Tea> teas =new ArrayList<>();if (!isEmpty(order.getTeas())){order.getTeas().forEach(tea -> {if (String.valueOf(tea.getState()).equals(state)){teas.add(tea);}});}return teas.size();}/*** 根据订单id 获取订单详情* @param orderId* @return*/public Order getOneOrder(String orderId){List<Order> orders= ORDER_TOOL.getOrderList();Order order=null;for (int i =0;i<orders.size();i++){Order order1 = orderList.get(i);if (orderId.equals(order1.getId())){order=order1;}}return order;}public Order updateTeaState(Order order, Tea tea){if (isEmpty(order.getTeas())){order.getTeas().stream().forEach(tea1 -> {if (tea1.getId().equals(tea.getId())){tea1.setState(tea.getState());}});}return order;}public Order updateCoffeeState(Order order,Coffee coffee){if (isEmpty(order.getCoffees())){order.getCoffees().stream().forEach(coffee1 -> {if (coffee1.getId().equals(coffee.getId())){coffee1.setState(coffee.getState());}});}return order;}public static OrderTool getOrderTool(){return ORDER_TOOL;}public Order createOrder(String id, String name, int teaNum, int coffeeNum){Order order=null;List<Order> orderList = ORDER_TOOL.getOrderList();//查询订单是否存在,存在获取现有订单for (int i =0;i<orderList.size();i++){Order order1 = orderList.get(i);if (id.equals(order1.getId())){order=order1;orderList.remove(order1);}}if (order==null){order=new Order();order.setId(id);}if (isBlank(order.getName())&&name!=null){order.setName(name);}List<Tea> teas =null;List<Coffee> coffees = null;if (isEmpty(order.getTeas())){teas= new ArrayList<>() ;}else {teas=order.getTeas();}if (isEmpty(order.getCoffees())){coffees= new ArrayList<>() ;}else {coffees=order.getCoffees();}//创建tea订单for (int i =0;i<teaNum;i++){Tea tea = new Tea();int num = (int)(Math.random()*10000);tea.setId(String.valueOf(num));tea.setOrderId(id);tea.setState(0);teas.add(tea);}//创建咖啡订单for (int i =0;i<coffeeNum;i++){Coffee coffee = new Coffee();int num = (int)(Math.random()*10000);coffee.setId(String.valueOf(num));coffee.setOrderId(id);coffee.setState(0);coffees.add(coffee);}if (!isEmpty(teas)){order.setTeas(teas);}if (!isEmpty(coffees)){order.setCoffees(coffees);}ORDER_TOOL.getOrderList().add(order);return order;}public String toOrderList(){return "list--"+toJson( ORDER_TOOL.getOrderList())+"size--"+ ORDER_TOOL.getOrderList().size();}public static boolean isBlank(final CharSequence cs) {int strLen;if (cs == null || (strLen = cs.length()) == 0) {return true;}for (int i = 0; i < strLen; i++) {if (Character.isWhitespace(cs.charAt(i)) == false) {return false;}}return true;}public static boolean isEmpty(Collection coll) {return (coll == null || coll.isEmpty());}public static String toJson(Object obj) {Gson gson = new Gson();return gson.toJson(obj);}public static void writeJson(String str){BufferedWriter writer = null;File file =new File("C:\\virtualCoffeeShop\\login.txt");if (!file.exists()){try {file.createNewFile();}catch (IOException e){System.out.println(e);}}try {writer = new BufferedWriter(new FileWriter(file));writer.write(str);}catch (IOException e){System.out.println(e);}finally {if (writer!=null){try {writer.close();}catch (Exception e){System.out.println(e);}}}}}