diff --git a/code/simplechat1/ClientConsole.java b/code/simplechat1/ClientConsole.java index c9bb4e9..746403b 100644 --- a/code/simplechat1/ClientConsole.java +++ b/code/simplechat1/ClientConsole.java @@ -1,122 +1,132 @@ + // This file contains material supporting section 3.7 of the textbook: // "Object Oriented Software Engineering" and is issued under the open-source // license found at www.lloseng.com + +import java.util.Scanner; import java.io.*; import client.*; import common.*; /** - * This class constructs the UI for a chat client. It implements the - * chat interface in order to activate the display() method. - * Warning: Some of the code here is cloned in ServerConsole + * This class constructs the UI for a chat client. It implements the chat + * interface in order to activate the display() method. Warning: Some of the + * code here is cloned in ServerConsole * * @author François Bélanger - * @author Dr Timothy C. Lethbridge + * @author Dr Timothy C. Lethbridge * @author Dr Robert Laganière * @version July 2000 */ -public class ClientConsole implements ChatIF -{ - //Class variables ************************************************* - - /** - * The default port to connect on. - */ - final public static int DEFAULT_PORT = 5555; - - //Instance variables ********************************************** - - /** - * The instance of the client that created this ConsoleChat. - */ - ChatClient client; - - - //Constructors **************************************************** - - /** - * Constructs an instance of the ClientConsole UI. - * - * @param host The host to connect to. - * @param port The port to connect on. - */ - public ClientConsole(String host, int port) - { - try - { - client= new ChatClient(host, port, this); - } - catch(IOException exception) - { - System.out.println("Error: Can't setup connection!" - + " Terminating client."); - System.exit(1); - } - } - - - //Instance methods ************************************************ - - /** - * This method waits for input from the console. Once it is - * received, it sends it to the client's message handler. - */ - public void accept() - { - try - { - BufferedReader fromConsole = - new BufferedReader(new InputStreamReader(System.in)); - String message; - - while (true) - { - message = fromConsole.readLine(); - client.handleMessageFromClientUI(message); - } - } - catch (Exception ex) - { - System.out.println - ("Unexpected error while reading from console!"); - } - } - - /** - * This method overrides the method in the ChatIF interface. It - * displays a message onto the screen. - * - * @param message The string to be displayed. - */ - public void display(String message) - { - System.out.println("> " + message); - } - - - //Class methods *************************************************** - - /** - * This method is responsible for the creation of the Client UI. - * - * @param args[0] The host to connect to. - */ - public static void main(String[] args) - { - String host = ""; - int port = 0; //The port number - - try - { - host = args[0]; - } - catch(ArrayIndexOutOfBoundsException e) - { - host = "localhost"; - } - ClientConsole chat= new ClientConsole(host, DEFAULT_PORT); - chat.accept(); //Wait for console data - } + +public class ClientConsole implements ChatIF { + // Class variables ************************************************* + + /** + * The default port to connect on. + */ + final public static int DEFAULT_PORT = 5555; + + // Instance variables ********************************************** + + /** + * The instance of the client that created this ConsoleChat. + */ + ChatClient client; + + // Constructors **************************************************** + + /** + * Constructs an instance of the ClientConsole UI. + * + * @param host The host to connect to. + * @param port The port to connect on. + * + */ + + // Modified for E7a: Take a username string to detect client username and loginId + public ClientConsole(String username, String host, int port) { + try { + client = new ChatClient(username, host, port, this); + } catch (IOException exception) { + System.out.println("Error: Can't setup connection!" + " Terminating client."); + System.exit(1); + } + } + + // Instance methods ************************************************ + + /** + * This method waits for input from the console. Once it is received, it sends + * it to the client's message handler. + */ + public void accept() { + try { + BufferedReader fromConsole = new BufferedReader(new InputStreamReader(System.in)); + String message; + + while (true) { + message = fromConsole.readLine(); + client.handleMessageFromClientUI(message); + } + } catch (Exception ex) { + System.out.println("Unexpected error while reading from console!"); + } + } + + /** + * This method overrides the method in the ChatIF interface. It displays a + * message onto the screen. + * + * @param message The string to be displayed. + */ + public void display(String message) { + System.out.println("> " + message); + } + + // Class methods *************************************************** + + /** + * This method is responsible for the creation of the Client UI. + * + * @param args[0] The host to connect to. + */ + public static void main(String[] args) { + String host = ""; + + int port =0; + String username = ""; + + // Modified for E7b: Require a login ID + try { + username = args[0]; + } catch (ArrayIndexOutOfBoundsException e) { + //System.err.println("ERROR - No login ID specified. Connection aborted."); + System.err.println("Cannot open connection. Awaiting command."); + //System.exit(0); + //return; + } + + try { + host = args[1]; + } catch (ArrayIndexOutOfBoundsException e) { + host = "localhost"; + } + + // Modified for E5b: Let user input the desired port number + try + { + port = Integer.parseInt(args[2]); + } + catch(ArrayIndexOutOfBoundsException e) + { + port = DEFAULT_PORT; + } + + ClientConsole chat = new ClientConsole(username, host,port); + chat.accept(); //Wait for console data + + } } //End of ConsoleChat class diff --git a/code/simplechat1/EchoServer.java b/code/simplechat1/EchoServer.java index d4f3a1a..3c1eed1 100644 --- a/code/simplechat1/EchoServer.java +++ b/code/simplechat1/EchoServer.java @@ -1,109 +1,220 @@ -// This file contains material supporting section 3.7 of the textbook: -// "Object Oriented Software Engineering" and is issued under the open-source -// license found at www.lloseng.com - -import java.io.*; -import ocsf.server.*; - -/** - * This class overrides some of the methods in the abstract - * superclass in order to give more functionality to the server. - * - * @author Dr Timothy C. Lethbridge - * @author Dr Robert Laganière - * @author François Bélanger - * @author Paul Holden - * @version July 2000 - */ -public class EchoServer extends AbstractServer -{ - //Class variables ************************************************* - - /** - * The default port to listen on. - */ - final public static int DEFAULT_PORT = 5555; - - //Constructors **************************************************** - - /** - * Constructs an instance of the echo server. - * - * @param port The port number to connect on. - */ - public EchoServer(int port) - { - super(port); - } - - - //Instance methods ************************************************ - - /** - * This method handles any messages received from the client. - * - * @param msg The message received from the client. - * @param client The connection from which the message originated. - */ - public void handleMessageFromClient - (Object msg, ConnectionToClient client) - { - System.out.println("Message received: " + msg + " from " + client); - this.sendToAllClients(msg); - } - - /** - * This method overrides the one in the superclass. Called - * when the server starts listening for connections. - */ - protected void serverStarted() - { - System.out.println - ("Server listening for connections on port " + getPort()); - } - - /** - * This method overrides the one in the superclass. Called - * when the server stops listening for connections. - */ - protected void serverStopped() - { - System.out.println - ("Server has stopped listening for connections."); - } - - //Class methods *************************************************** - - /** - * This method is responsible for the creation of - * the server instance (there is no UI in this phase). - * - * @param args[0] The port number to listen on. Defaults to 5555 - * if no argument is entered. - */ - public static void main(String[] args) - { - int port = 0; //Port to listen on - - try - { - port = Integer.parseInt(args[0]); //Get port from command line - } - catch(Throwable t) - { - port = DEFAULT_PORT; //Set port to 5555 - } - - EchoServer sv = new EchoServer(port); - - try - { - sv.listen(); //Start listening for connections - } - catch (Exception ex) - { - System.out.println("ERROR - Could not listen for clients!"); - } - } -} -//End of EchoServer class +// This file contains material supporting section 3.7 of the textbook: +// "Object Oriented Software Engineering" and is issued under the open-source +// license found at www.lloseng.com + + +import java.io.IOException; +import java.util.Scanner; + +import ocsf.server.*; + + +/** + * This class overrides some of the methods in the abstract + * superclass in order to give more functionality to the server. + * + * @author Dr Timothy C. Lethbridge + * @author Dr Robert Laganière + * @author François Bélanger + * @author Paul Holden + * @version July 2000 + */ + +public class EchoServer extends AbstractServer { + + // Class variables ************************************************* + + /** + * The default port to listen on. + */ + final public static int DEFAULT_PORT = 5555; + + // Constructors **************************************************** + + /** + * Constructs an instance of the echo server. + * + * @param port The port number to connect on. + */ + public EchoServer(int port) { + super(port); + } + + // Instance methods ************************************************ + + /** + * This method handles any messages received from the client. + * + * @param msg The message received from the client. + * @param client The connection from which the message originated. + * + */ + + // Modified for E7c: Receive #login command from the client + public void handleMessageFromClient(Object msg, ConnectionToClient client) { + String message = msg.toString(); + if (message.startsWith("#login")){ + System.out.println("Message received: " + msg + " from " + client); + this.sendToAllClients(msg); + } + + if (message.startsWith("#")) { + String[] params = message.substring(1).split(" "); + if (params[0].equalsIgnoreCase("login") && params.length > 1) { + if (client.getInfo("username") == null) { + client.setInfo("username", params[1]); + } else { + try { + Object sendToClientMsg = "Username has already been set!"; + client.sendToClient(sendToClientMsg); + } catch (IOException e) { + } + } + + } + } else { + if (client.getInfo("username") == null) { + try { + Object sendToClientMsg = "Set a username before messaging the server!"; + client.sendToClient(sendToClientMsg); + client.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + System.out.println("Message received: " + msg + " from " + client.getInfo("username")); + Object sendToClientMsg = client.getInfo("username") + ">" + message; + this.sendToAllClients(sendToClientMsg); + } + } + + } + + /** + * This method overrides the one in the superclass. Called when the server + * starts listening for connections. + */ + protected void serverStarted() { + System.out.println("Server listening for connections on port " + getPort()); + } + + /** + * This method overrides the one in the superclass. Called when the server stops + * listening for connections. + */ + protected void serverStopped() { + System.out.println("Server has stopped listening for connections."); + } + + // Modified for E5c: Print message when client connect/disconnect + protected void clientConnected(ConnectionToClient client) { + System.out.println( + "Client successfully connected"); + } + + synchronized protected void clientDisconnected(ConnectionToClient client) { + System.out.println("Client successfully disconnected."); + } + + synchronized protected void clientException(ConnectionToClient client, Throwable exception) { + try{ + System.out.println("Client successfully disconnected"); + client.close(); + } + catch(IOException e){} + + } + + // Class methods *************************************************** + + /** + * This method is responsible for the creation of the server instance (there is + * no UI in this phase). + * + * @param args[0] The port number to listen on. Defaults to 5555 if no argument + * is entered. + */ + + // Modified for E5b: Let user input the desired port number + public static void main(String[] args) { + // Scanner scan = new Scanner(System.in); + // System.out.println("Enter any port number"); + int port = 0; // Port to listen on + + try { + port = Integer.parseInt(args[0]); // Get port from command line + } catch (Throwable t) { + //port = scan.nextInt(); // Set port to whatever the user wants! + port = DEFAULT_PORT; //Set port to 5555 + } + + EchoServer sv = new EchoServer(port); + + try { + sv.listen(); // Start listening for connections + + } catch (Exception ex) { + System.out.println("ERROR - Could not listen for clients!"); + } + } + + // Modified for E6c: User can type commands in Server side commands + public void handleMessageFromServerConsole(String message) { + if (message.startsWith("#")) { + String[] parameters = message.split(" "); + String command = parameters[0]; + switch (command) { + case "#quit": + // closes the server and then exits it + try { + System.out.println("Quit..."); + this.close(); + } catch (IOException e) { + System.exit(1); + } + System.exit(0); + break; + case "#stop": + this.stopListening(); + this.sendToAllClients("Server stopped listening for new connections."); + break; + case "#close": + try { + System.out.println("Server disconnected from client"); + this.close(); + } catch (IOException e) { + } + break; + case "#setport": + if (!this.isListening() && this.getNumberOfClients() < 1) { + super.setPort(Integer.parseInt(parameters[1])); + System.out.println("Port set to " + Integer.parseInt(parameters[1])); + } else { + System.out.println("Cannot do this command while the server is connected."); + } + break; + case "#start": + if (!this.isListening()) { + try { + this.listen(); + } catch (IOException e) { + // error listening for clients + } + } else { + System.out.println("Already started listening for clients."); + } + break; + case "#getport": + System.out.println("Currently on port " + this.getPort()); + break; + default: + System.out.println("Invalid command: '" + command + "'"); + break; + } + } else { + this.sendToAllClients("Server: " + message); + } + } + + } + //End of EchoServer class \ No newline at end of file diff --git a/code/simplechat1/ServerConsole.java b/code/simplechat1/ServerConsole.java new file mode 100644 index 0000000..a159b9b --- /dev/null +++ b/code/simplechat1/ServerConsole.java @@ -0,0 +1,77 @@ + +// Modified for E6b: Allowing user input +// Similar to ClientConsole with minor changes to reflect how the server handle messages + + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import common.ChatIF; +import ocsf.server.*; + +public class ServerConsole implements ChatIF { + + /** + * The default port to connect on. + */ + final public static int DEFAULT_PORT = 5555; + + EchoServer server; + + public ServerConsole(int port) { + server = new EchoServer(port); + try { + server.listen(); + } catch (IOException e) { + System.out.println("ERROR - Could not listen for clients!"); + } + } + + // Instance methods ************************************************ + + /** + * This method waits for input from the console. Once it is received, it sends + * it to all of the clients + */ + public void accept() { + try { + BufferedReader fromConsole = new BufferedReader(new InputStreamReader(System.in)); + String message; + + while ((message = fromConsole.readLine()) != null) { + server.handleMessageFromServerConsole(message); + this.display(message); + } + } catch (Exception ex) { + System.out.println("Unexpected error while reading from console!"); + } + } + + // Class methods *************************************************** + + /** + * This method is responsible for the creation of the Client UI. + * + * @param args The port to use for connection + */ + public static void main(String[] args) { + int port = 0; // Port to listen on + + try { + port = Integer.parseInt(args[0]); // Get port from command line + } catch (Throwable t) { + port = DEFAULT_PORT; // Set port to 5555 + } + + ServerConsole serv = new ServerConsole(port); + serv.accept(); + } + + @Override + public void display(String message) { + // TODO Auto-generated method stub + + } + +} diff --git a/code/simplechat1/client/ChatClient.java b/code/simplechat1/client/ChatClient.java index fe1401e..49849d4 100644 --- a/code/simplechat1/client/ChatClient.java +++ b/code/simplechat1/client/ChatClient.java @@ -9,86 +9,154 @@ import java.io.*; /** - * This class overrides some of the methods defined in the abstract - * superclass in order to give more functionality to the client. + * This class overrides some of the methods defined in the abstract superclass + * in order to give more functionality to the client. * * @author Dr Timothy C. Lethbridge * @author Dr Robert Laganiè * @author François Bélanger * @version July 2000 */ -public class ChatClient extends AbstractClient -{ - //Instance variables ********************************************** - - /** - * The interface type variable. It allows the implementation of - * the display method in the client. - */ - ChatIF clientUI; - - - //Constructors **************************************************** - - /** - * Constructs an instance of the chat client. - * - * @param host The server to connect to. - * @param port The port number to connect on. - * @param clientUI The interface type variable. - */ - - public ChatClient(String host, int port, ChatIF clientUI) - throws IOException - { - super(host, port); //Call the superclass constructor - this.clientUI = clientUI; - openConnection(); - } - - - //Instance methods ************************************************ - - /** - * This method handles all data that comes in from the server. - * - * @param msg The message from the server. - */ - public void handleMessageFromServer(Object msg) - { - clientUI.display(msg.toString()); - } - - /** - * This method handles all data coming from the UI - * - * @param message The message from the UI. - */ - public void handleMessageFromClientUI(String message) - { - try - { - sendToServer(message); - } - catch(IOException e) - { - clientUI.display - ("Could not send message to server. Terminating client."); - quit(); - } - } - - /** - * This method terminates the client. - */ - public void quit() - { - try - { - closeConnection(); - } - catch(IOException e) {} - System.exit(0); - } +public class ChatClient extends AbstractClient { + // Instance variables ********************************************** + + /** + * The interface type variable. It allows the implementation of the display + * method in the client. + */ + ChatIF clientUI; + String username; + + // Constructors **************************************************** + + /** + * Constructs an instance of the chat client. + * + * @param host The server to connect to. + * @param port The port number to connect on. + * @param clientUI The interface type variable. + */ + + public ChatClient(String username, String host, int port, ChatIF clientUI) throws IOException { + super(host, port); // Call the superclass constructor + this.clientUI = clientUI; + this.username = username; + openConnection(); + + // Modified for E7a: Automatic login + this.sendToServer("#login " + username); + + } + + // Instance methods ************************************************ + + /** + * This method handles all data that comes in from the server. + * + * @param msg The message from the server. + */ + public void handleMessageFromServer(Object msg) { + clientUI.display(msg.toString()); + } + + /** + * This method handles all data coming from the UI + * + * @param message The message from the UI. + */ + + // Modified for E6a: Client can type commands starting with # for special functions + public void handleMessageFromClientUI(String message) { + if (message.startsWith("#")) { + String[] splitMessage = message.split(" "); + String fstPart_Msg = splitMessage[0]; + switch (fstPart_Msg) { + case "#quit": + quit(); + break; + case "#logoff": + try { + System.out.println("Connection is closed."); + closeConnection(); + } catch (IOException e) { + System.out.println("Error closing connection."); + } + break; + case "#sethost": + if (this.isConnected()) { + System.out.println("Can't do that now. Already connected."); + } else { + super.setHost(splitMessage[1]); + } + break; + case "#setport": + if (this.isConnected()) { + System.out.println("Can't do that now. Already connected."); + } else { + this.setPort(Integer.parseInt(splitMessage[1])); + } + break; + case "#login": + if (this.isConnected()) { + System.out.println("Can't do that now. Already connected."); + } else { + try { + this.openConnection(); + } catch (IOException e) { + System.out.println("Error opening connection to server. Perhaps the server is not running!"); + } + } + break; + case "#gethost": + System.out.println("Current host is " + this.getHost()); + break; + case "#getport": + System.out.println("Current port is " + this.getPort()); + break; + default: + System.out.println("Invalid command: '" + fstPart_Msg + "'"); + break; + } + } else { + try { + sendToServer(message); + } catch (IOException e) { + clientUI.display("Could not send message to server. Terminating client."); + quit(); + } + } + + } + + /** + * This method terminates the client. + */ + public void quit() { + try { + clientUI.display("Terminating..."); + closeConnection(); + } catch (IOException e) { + } + System.exit(0); + } + + // Modified for E5a: Respond to shutdown of server by printing a message and quitting + public void connectionClosed() { + + try { + if (!isConnected()) { + closeConnection(); + } + } catch (IOException e) { + connectionException(e); + } + + } + // Modified for E5a: Respond to shutdown of server by printing a message and quitting + protected void connectionException(Exception exception) { + System.out.println("The server has shut down, quitting now!"); + System.exit(0); + } + } //End of ChatClient class