java使用socket模拟咖啡馆场景,客户与服务器多线程交互场景
任务的目标是使用客户机 - 服务器架构构建一个"虚拟咖啡馆"系统每个客户端应用程序将扮演 Customer 谁想点茶或咖啡。服务器应用程序将扮演咖啡馆虚拟的角色 Barista 负责处理订单,准备茶和啡,并将订单交还给客户
- 启动Socket服务
java
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 object
try {
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.");
}
}
}
- 发送客户端
java
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();
}
}
@Override
public 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("");
}
}
}
}
}
- 咖啡制造区
java
public class MakeCoffeeArea extends Thread {
/**
* 制作coffee
*
* @param
*/
@Override
public 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());
}
}
}
- 茶制作区
java
public class MakeTeaArea extends Thread {
@Override
public 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());
}
}
}
- 托盘区
java
public class TrayArea extends Thread{
@Override
public 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();
}
}
}
}
}
- 等候区
java
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;
}
}
- 线程队列
java
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));
}
}
}
java
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);
}
}
@Override
public 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;
}
}
java
public class ServerAccept extends Thread{
@Override
public 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);
}
}
}
java
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);
}
}
}
}
}