// Autor: Antonín Daněk import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.Random; public class server { public int PORT=3555; public server(String port){ PORT=Integer.valueOf(port); Service s = new Service(); s.start(); try{ System.out.println("Will try to start server on port: " + PORT); ServerSocket ss = new ServerSocket(PORT); System.out.println("Server started on port: " + PORT); while (true) { System.out.println("Waiting for the client"); Socket sck = ss.accept(); if(s.add(new BufferedReader(new InputStreamReader(sck.getInputStream())), new PrintWriter(sck.getOutputStream(), true))){ } else System.out.println("too many connections"); /* try{ Thread.sleep(10); } catch(InterruptedException e){ e.printStackTrace(); } */ } } catch (IOException ex) { System.err.print("Server creation failed on port " + PORT); } } public static void main(String [] args) { if(args.length!=1) System.out.println("Usage: server "); else new server(args[0]); } } // It provides services for the clients, respondes to their requests class Service implements Runnable{ Random rnd = new Random(); public static final int MAX_CONNECTION=20; int clientCount=0; private Thread th=null; ArrayList br = new ArrayList(); ArrayList pw = new ArrayList(); ArrayList rs = new ArrayList(); public Service() { } // adds new client to the array lists, if number of connections is not over limit boolean add(BufferedReader b, PrintWriter p){ if(clientCount < MAX_CONNECTION){ br.add(b); pw.add(p); rs.add(new RobotState()); // sends "welcome message" to the client pw.get(clientCount).print("220 Ahoj, tady je robot. Oslovuj mne "+ rs.get(clientCount).robotsName +"." + "\r\n"); pw.get(clientCount).flush(); System.out.println("Client " + clientCount +" connected"); clientCount++; return true; } else return false; } public void start(){ th = new Thread(this); th.start(); } @Override public void run(){ int commandType; // server never ends while(true){ //System.out.println("Number of actually connected clients: "+ clientCount); // This got to be here, otherwise its not working on FEL servers. I guess, there is some // code optimalization and because clientCount is zero in the begining, it seems to optimizer as // useless cycle System.out.print(""); // go throuhgt the array of clients and responde to their request / close their connections for (int i = 0; i < clientCount; i++) { waitForData(i); if(rs.get(i).dataReady) { rs.get(i).dataReady=false; commandType = getTypeOfCommand(i); if(commandType==-1) { System.out.println("Client " + i + " sent: " + rs.get(i).fromClient); System.out.println("Response to client " + i + ": 500 NEZNAMY PRIKAZ"); pw.get(i).print("500 NEZNAMY PRIKAZ" +"\r\n"); pw.get(i).flush(); } if(commandType==1) { step(i); } if(commandType==2) { left(i); } if(commandType==3) { pickUp(i); } if(commandType==4) { repair(i); } } } } } // tries to repair the robot and sends message void repair(int i) { int clWantsToRepair = Integer.parseInt(rs.get(i).fromClient.split(" ")[1]); if(clWantsToRepair>0 && clWantsToRepair<10) { // does client want to repair the part which is broken? if(clWantsToRepair==rs.get(i).broken) { System.out.println("Client " + i + " sent: " + rs.get(i).fromClient); System.out.println("Response to client " + i + ": 250 OK ("+rs.get(i).positionX+","+rs.get(i).positionY+")"); rs.get(i).broken=0; pw.get(i).print("250 OK ("+rs.get(i).positionX+","+rs.get(i).positionY+")" + "\r\n"); pw.get(i).flush(); } else { System.out.println("Client " + i + " sent: " + rs.get(i).fromClient); System.out.println("Response to client " + i + ": 571 NENI PORUCHA"); pw.get(i).print("571 NENI PORUCHA" + "\r\n"); pw.get(i).flush(); remove(i); } } else { // client is trying to repair blok, which doesn't exist System.out.println("Client " + i + " sent: " + rs.get(i).fromClient); System.out.println("Response to client " + i + ": 500 NEZNAMY PRIKAZ"); pw.get(i).print("500 NEZNAMY PRIKAZ" + "\r\n"); pw.get(i).flush(); } } // end the connection with particular client and removes him from array list void remove(int i) { System.out.println("Closing connection with client: " + i); pw.get(i).close(); try{ br.get(i).close(); } catch(IOException e) { System.out.println("Closeing connection with client " + i + " failed."); } pw.remove(i); br.remove(i); rs.remove(i); clientCount--; } // tries to pick up the secret and sends message void pickUp(int i){ //Is the robot on the field with the secret? if(rs.get(i).positionX==0 && rs.get(i).positionY==0) { pw.get(i).print("221 USPECH " + rs.get(i).SECRET + "\r\n"); System.out.println("Client " + i + " sent: " + rs.get(i).fromClient); System.out.println("Response to client " + i + ": 221 USPECH " + rs.get(i).SECRET); } else { pw.get(i).print("550 NELZE ZVEDNOUT ZNACKU" + "\r\n"); System.out.println("Client " + i + " sent: " + rs.get(i).fromClient); System.out.println("Response to client " + i + ": 550 NELZE ZVEDNOUT ZNACKU"); } pw.get(i).flush(); remove(i); } // makes one step and sends message void step(int i){ // when client tries to make step when robot is broken if(rs.get(i).broken!=0) { pw.get(i).print("572 ROBOT SE ROZPADL" + "\r\n"); pw.get(i).flush(); System.out.println("Client " + i + " sent: " + rs.get(i).fromClient); System.out.println("Response to client " + i + ": 572 ROBOT SE ROZPADL"); remove(i); return; } // radomly generated failures of robot if(rs.get(i).stepsWithoutDefect>0 && (rnd.nextBoolean() || rs.get(i).stepsWithoutDefect==10)) { rs.get(i).broken=rnd.nextInt(10); if(rs.get(i).broken==0) rs.get(i).broken++; pw.get(i).print("570 PORUCHA BLOK " + rs.get(i).broken + "\r\n"); pw.get(i).flush(); System.out.println("Client " + i + " sent: " + rs.get(i).fromClient); System.out.println("Response to client " + i + ": 570 PORUCHA BLOK " + rs.get(i).broken); rs.get(i).stepsWithoutDefect=0; return; } // robot is fine, make step in right direction if(rs.get(i).rotation==0) rs.get(i).positionY+=1; // up if(rs.get(i).rotation==1) rs.get(i).positionX+=1; // right if(rs.get(i).rotation==2) rs.get(i).positionY-=1; // down if(rs.get(i).rotation==3) rs.get(i).positionX-=1; // left // was the step in the field? if(rs.get(i).positionY>=-17 && rs.get(i).positionY<=17 && rs.get(i).positionX>=-17 && rs.get(i).positionX<=17){ pw.get(i).print("250 OK ("+rs.get(i).positionX+","+rs.get(i).positionY+")" + "\r\n"); pw.get(i).flush(); System.out.println("Client " + i + " sent: " + rs.get(i).fromClient); System.out.println("Response to client " + i + ": 250 OK ("+rs.get(i).positionX+","+rs.get(i).positionY+")"); rs.get(i).stepsWithoutDefect++; } else { pw.get(i).print("530 HAVARIE" + "\r\n"); pw.get(i).flush(); System.out.println("Client " + i + " sent: " + rs.get(i).fromClient); System.out.println("Response to client " + i + ": 530 HAVARIE"); remove(i); } } // makes turn to the left and sends message void left(int i){ rs.get(i).rotation--; if(rs.get(i).rotation<0) rs.get(i).rotation=3; pw.get(i).print("250 OK ("+rs.get(i).positionX+","+rs.get(i).positionY+")" + "\r\n"); pw.get(i).flush(); System.out.println("Client " + i + " sent: " + rs.get(i).fromClient); System.out.println("Response to client " + i + ": 250 OK ("+rs.get(i).positionX+","+rs.get(i).positionY+")"); } // waits for data from client and save it into member fromClient void waitForData(int i){ // System.out.println("Waiting for data from client: "+ i); int fs=-1; rs.get(i).fromClient=""; try{ /* try{ Thread.sleep(10); } catch(InterruptedException e){ e.printStackTrace(); } */ if(br.get(i).ready()) { rs.get(i).dataReady=true; } else { // System.out.println("Client " + i + "wasn't ready. Let's continue to other client."); return; } boolean CR=false,LF=false; // client sent data, lets recieve it while (true){ fs = br.get(i).read(); if(CR || fs==13) CR=true; if(CR && fs==10) LF=true; else if (fs!=13) CR=false; // System.out.print(fs + " "); if(rs.get(i).fromClient.length()<(rs.get(i).robotsName.length()+50)) { rs.get(i).fromClient+=(char)fs; } //finishing tag arrived if(LF) { if(rs.get(i).fromClient.length()<(rs.get(i).robotsName.length()+50)) {} else { // client sent me some freaky long string pw.get(i).print("500 NEZNAMY PRIKAZ" + "\r\n"); pw.get(i).flush(); System.out.println("Client " + i + " is probably hacker! He sent: " + rs.get(i).fromClient); System.out.println("Sending: 500 NEZNAMY PRIKAZ"); rs.get(i).dataReady=false; return; } break; } } } catch(IOException e){ e.printStackTrace(); } if(rs.get(i).fromClient.endsWith("\r\n")) rs.get(i).fromClient = rs.get(i).fromClient.substring(0, rs.get(i).fromClient.indexOf("\r\n")); else System.out.println("chyba, neobsahuje ukoncovaci znaky \r\n"); System.out.println("Data accepted (" + rs.get(i).fromClient + ") from client: " + i); } // returns type of command> -1:unknown; 1:krok; 2: vlevo; 3: zvedni; 4: opravit int getTypeOfCommand(int i){ //client didn't use my name if(!rs.get(i).fromClient.startsWith(rs.get(i).robotsName)) return -1; else { //delete my name from the message rs.get(i).fromClient = rs.get(i).fromClient.substring(rs.get(i).robotsName.length()+1); String[] substrings = rs.get(i).fromClient.split(" "); if(substrings[0].equals("KROK")) {return 1;} if(substrings[0].equals("VLEVO")) {return 2;} if(substrings[0].equals("ZVEDNI")) {return 3;} if(substrings[0].equals("OPRAVIT")) {return 4;} } return -1; } } //represents robots state class RobotState { public final String robotsName= "Ty pekelny stroji" , SECRET="DONT TELL ENYONE, IT'S A SECRET ... BLA BLA BLA."; String fromClient=""; int stepsWithoutDefect=0; boolean dataReady=false; /** * position of the robot */ int positionX; int positionY; int rotation; int broken=0; Random rnd = new Random(); /** buffer size in bytes */ int sz = 1024 * 512; /** initiolized size of StringBuilder */ StringBuilder sb = new StringBuilder(2*sz); // random generation of the position and rotation of the robot public RobotState(){ positionX = rnd.nextInt(17); if(rnd.nextBoolean()) positionX=positionX-2*positionX; positionY = rnd.nextInt(17); if(rnd.nextBoolean()) positionY=positionY-2*positionY; rotation = rnd.nextInt(4); // 0-up;1-right;2-down;3-left } }