Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
COM561S2 - Concurrent and Distributed Computing (15-16) Assignment 2 SOLUTIONS Solution 1 (a) Single Threaded Client/Server System has the following interaction: Server waits for connections from clients When connection made the server sends a message to the client prompting for the student number Client user types in the student number and sends it to the server. Server reads the student number and searches the list of records for associated Student name and results. Student name and results are forwarded to the client, who reads and displays them (if the student number is invalid this is indicated to the client). The Client can keep requesting student details until it terminates the communication by entering the value -1. The Server waits for the next client to connect. UML Diagram - Client and Iterative Server The client code consists of one class StudentAdminClient in a separate project with a JAR file of StudentDetailsType in the Libraries folder. import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; 1 import java.net.Socket; import studentdetailstype.StudentDetailsType; public class StudentAdminClient { public static void main(String[] args) { String hostName = "localhost"; // default host name int hostPort = 4444; // default host port // assign host machine name and port to connect to if (args.length != 0) { if (args[0] != null) { hostName = args[0]; // user specified machine } if (args[1] != null) { hostPort = Integer.parseInt(args[1]); // user specified port } } System.out.println("Tyring to Connect to Student Admin Server"); // connect to server and extract input and output streams try (Socket serverSocket = new Socket(hostName, hostPort); PrintWriter os = new PrintWriter(new BufferedWriter(new OutputStreamWriter(serverSocket.getOutputStream()))); ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(serverSocket.getInputStream()))) { // read and display opening message from server System.out.println("Server: " + is.readObject()); // create client input stream BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in)); System.out.print("Enter student number (-1 to quit): "); String message = userInput.readLine(); while (!message.equals("-1")) { sendMessageToServer(os, message); handleResponse((StudentDetailsType)is.readObject()); System.out.print("Enter student number (-1 to quit): "); message = userInput.readLine(); } // sent termination request to server sendMessageToServer(os, message); // read closing message from server and display it System.out.println(is.readObject()); } catch (Exception e) { System.err.println("Exception: " + e.getMessage()); } } public static void sendMessageToServer(PrintWriter os, String msg) { os.println(msg); os.flush(); } public static void handleResponse(StudentDetailsType sDetails) { // attempt to read the StudentDetailsType object 2 if (sDetails != null) { System.out.println("Server: " + formatStudentDetails(sDetails)); } else { System.out.println("Server: Invalid Student Number\n"); } } public static String formatStudentDetails(StudentDetailsType s) { StringBuilder b = new StringBuilder(); b.append("STUDENT NAME: " + s.getStudentName()+"\n"); b.append(String.format("\tMark1 = " + "%.2f\n", s.getResult1())); b.append(String.format("\tMark2 = " + "%.2f\n", s.getResult2())); b.append(String.format("\tMark3 = " + "%.2f\n\n", s.getResult3())); return b.toString(); } } The Iterative Server code is composed of two classes StudentAdminServerIterative – main server class and the StudentData class both in the same project. A JAR file of StudentDetailsType is also available in the Libraries folder of this project. import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import java.io.ObjectOutputStream; import studentdetailstype.StudentDetailsType; import java.io.*; public class StudentAdminServerIterative { public static void main(String[] args) { // determine if port to listen on is specified by user else use default int portNumber = 4444; // default port number if (args.length == 1) { portNumber = Integer.parseInt(args[0]); // user specified port number } System.out.println("Student Server Started"); // create serverSocket to listen on try (ServerSocket serverSocket = new ServerSocket(portNumber)) { while (true) { Socket clientSocket = serverSocket.accept(); try (BufferedReader is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); ObjectOutputStream os = new ObjectOutputStream(new BufferedOutputStream(clientSocket.getOutputStream()))) { System.out.println("Client Accepted"); // send initial prompt to client sendMessageToClient(os, "Server Saying Hello"); // send initial message to client int num = parseToInt(is.readLine()); // read response from client and convert to integer while (num != -1) { // send studentDetails to client sendMessageToClient(os, handleRequest(num)); num = parseToInt(is.readLine()); // read response from client and convert to integer } // send closing message to client sendMessageToClient(os, "Server saying Goodby\n"); 3 } catch (IOException e) { System.out.println("IOException:" + e.getMessage()); } } // end while true } catch (Exception e) { System.out.println("Exception:" + e.getMessage()); } // end catch } // end main public static void sendMessageToClient(ObjectOutputStream os, Object msg) throws Exception { os.writeObject(msg); os.flush(); } public static StudentDetailsType handleRequest(int studentNumber) { StudentData studentData = new StudentData(); // read student number from client, then generate and send response StudentDetailsType response = null; if (new StudentData().validStudentNumberFlag(studentNumber)) { response = studentData.getStudentDetails(studentNumber); } return response; } public static int parseToInt(String s) { int studentNumber = 0; try { studentNumber = Integer.parseInt(s); } catch (NumberFormatException e) { System.out.println("Unable to read client command"); } return studentNumber; } } Typical interaction activity is as follows Iterative Server running with one client connected and another trying to connect. 4 (b) Multi-Threaded Server System has the same interaction with each client as the Iterative server, however it can communicate with a number of clients concurrently. UML Diagram - Client and Multi-Threaded Server The Multi-Threaded Server code is composed of two classes StudentAdminServerMultiThreaded and StudentData both in the same project. A JAR file of StudentDetailsType is also available in the Libraries folder of this project. import java.net.*; import java.io.*; import studentdetailstype.StudentDetailsType; public class StudentAdminServerMultiThreaded extends Thread { /* This server acts as a multi-threaded "StudentAdminServerMultiThreaded" server. * A number of clients can connect at once. * It prompts for a Student Number * from any connected client returns the appropriate student details. */ private final Socket clientSocket; // client socket for each thread connected // Constructor StudentAdminServerMultiThreaded(Socket clientSocket) { this.clientSocket = clientSocket; 5 } // end constructor // run method for thread @Override public void run() { try (BufferedReader is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); ObjectOutputStream os = new ObjectOutputStream(new BufferedOutputStream(clientSocket.getOutputStream()))) { // send initial prompt to client sendMessageToClient(os, "Server Saying Hello"); // send initial message to client int num = parseToInt(is.readLine()); // read response from client and convert to integer while (num != -1) { // send studentDetails to client sendMessageToClient(os, handleRequest(num)); num = parseToInt(is.readLine()); // read response from client and convert to integer } // send closing message to client sendMessageToClient(os, "Server saying Goodby\n"); } catch (Exception e) { System.out.println("IOException:" + e.getMessage()); } } // end run public static void main(String[] args) { // determine if port to listen on is specified by user else use default int portNumber = 4444; // default port number if (args.length == 1) { portNumber = Integer.parseInt(args[0]); // user specified port number } System.out.println("Student Server Started"); // create serverSocket to listen on try (ServerSocket serverSocket = new ServerSocket(portNumber)) { while (true) { System.out.println("Multi Threaded Server Waiting"); Socket clientSocket = serverSocket.accept(); System.out.println("Client Accepted from " + clientSocket.getInetAddress()); // spawn a new thread to handle client StudentAdminServerMultiThreaded studentAdminServerThread = new StudentAdminServerMultiThreaded(clientSocket); System.out.println("About to start new thread"); studentAdminServerThread.start(); } // end while true } catch (Exception e) { System.out.println("Exception:" + e.getMessage()); } // end catch } // end main public static void sendMessageToClient(ObjectOutputStream os, Object msg) throws Exception { os.writeObject(msg); os.flush(); } public static StudentDetailsType handleRequest(int studentNumber) { StudentData studentData = new StudentData(); // read student number from client, then generate and send response StudentDetailsType response = null; if (new StudentData().validStudentNumberFlag(studentNumber)) { response = studentData.getStudentDetails(studentNumber); } return response; } 6 public static int parseToInt(String s) { int studentNumber = 0; try { studentNumber = Integer.parseInt(s); } catch (NumberFormatException e) { System.out.println("Unable to read client command"); } return studentNumber; } } // end StudentAdminServerMultiThreaded Typical interaction activity is as follows Multi-threaded Server running with two client connected and communicating. 7 Solution 2 UML Diagram - Client and Multi-Threaded Server The Multi-Threaded Server code (with database support) is composed of two classes StudentAdminServerMultiThreadedDatabase and the StudentDataDB class, both in the same project. A JAR file of StudentDetailsType is also available in the Libraries folder of this project. import java.net.*; import java.io.*; import studentdetailstype.StudentDetailsType; public class StudentAdminServerMultiThreadedDatabase extends Thread { /* This server acts as a multi-threaded "StudentAdminServerMultiThreadedDatabase" server. * A number of clients can connect at once. * It prompts for a Student Number * from any connected client returns the appropriate student details. */ private final Socket clientSocket; // client socket for each thread connected // Constructor StudentAdminServerMultiThreadedDatabase(Socket clientSocket) { this.clientSocket = clientSocket; } // end constructor // run method for thread @Override public void run() { try (BufferedReader is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); ObjectOutputStream os = new ObjectOutputStream(new BufferedOutputStream(clientSocket.getOutputStream()))) { // send initial prompt to client sendMessageToClient(os, "Server Saying Hello"); // send initial message to client int num = parseToInt(is.readLine()); // read response from client and convert to integer while (num != -1) { // send studentDetails to client sendMessageToClient(os, handleRequest(num)); num = parseToInt(is.readLine()); // read response from client and convert to integer } 8 // send closing message to client sendMessageToClient(os, "Server saying Goodby\n"); } catch (Exception e) { System.out.println("IOException:" + e.getMessage()); } } // end run public static void main(String[] args) { // determine if port to listen on is specified by user else use default int portNumber = 4444; // default port number if (args.length == 1) { portNumber = Integer.parseInt(args[0]); // user specified port number } System.out.println("Student Server Started"); // create serverSocket to listen on try (ServerSocket serverSocket = new ServerSocket(portNumber)) { while (true) { System.out.println("Multi Threaded Server Waiting (with database) "); Socket clientSocket = serverSocket.accept(); System.out.println("Client Accepted from " + clientSocket.getInetAddress()); // spawn a new thread to handle client StudentAdminServerMultiThreadedDatabase studentAdminServerThread = new StudentAdminServerMultiThreadedDatabase(clientSocket); System.out.println("About to start new thread"); studentAdminServerThread.start(); } // end while true } catch (Exception e) { System.out.println("Exception:" + e.getMessage()); } // end catch } // end main public static void sendMessageToClient(ObjectOutputStream os, Object msg) throws Exception { os.writeObject(msg); os.flush(); } public static StudentDetailsType handleRequest(int studentNumber) { StudentDataDB studentDataDB = new StudentDataDB(); // read student number from client, then generate and send response StudentDetailsType response = null; if (new StudentDataDB().validStudentNumberFlag(studentNumber)) { response = studentDataDB.getStudentDetails(studentNumber); } return response; } public static int parseToInt(String s) { int studentNumber = 0; try { studentNumber = Integer.parseInt(s); } catch (NumberFormatException e) { System.out.println("Unable to read client command"); } return studentNumber; } } // end StudentAdminServerMultiThreadedDatabase import java.sql.Connection; 9 import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import studentdetailstype.StudentDetailsType; public class StudentDataDB { ResultSet rs; public StudentDataDB() { //constructor try { String host = "jdbc:derby://localhost:1527/StudentDataDB"; String uName = "Tom"; String pWord = "MG121DTL"; Connection con = DriverManager.getConnection(host, uName, pWord); Statement stmt = con.createStatement(); String SQL = "SELECT * FROM STUDENTDATA"; rs = stmt.executeQuery(SQL); } catch (SQLException err) { System.out.println(err.getMessage()); } } // end constructor public boolean validStudentNumberFlag(int studentNum) { try { while (rs.next()) { if (studentNum == rs.getInt("STUDENTID")) { return (true); } } } catch (SQLException err) { System.out.println(err.getMessage()); } return (false); } //end validStudentNumberFlag public StudentDetailsType getStudentDetails(int studentNum) { try { while (rs.next()) { if (studentNum == rs.getInt("STUDENTID")) { // get the database details and create a StudentDetailsType object String name = rs.getString("NAME"); float result1 = rs.getFloat("RESULT1"); float result2 = rs.getFloat("RESULT2"); float result3 = rs.getFloat("RESULT3"); return(new StudentDetailsType(studentNum, name, result1, result2, result3)); } } } catch (SQLException err) { System.out.println(err.getMessage()); } return null; } //end getStudentDetails } // end StudentDataDB Typical interaction activity is as follows Multi-threaded Server (with JavaDB database) running with two client connected and communicating. 10 Testing Invalid Input Testing a Client Terminating 11 END 12