Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of 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