scp-app

git clone git://git.codymlewis.com/scp-app.git
Log | Files | Refs | LICENSE

commit 56ac9d3bed2be75ff5ad63254bc16526fa983372
parent 1d1b00c359777febd848f646eb328d566bc7648d
Author: Cody Lewis <luxdotsugi@gmail.com>
Date:   Sat,  1 Sep 2018 00:09:20 +1000

Added a GUI, and made the app run as full duplex

Diffstat:
DAssessmentItemCoverSheet.pdf | 0
MChat.java | 119++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
MChatClient.java | 61++++++++++++++-----------------------------------------------
MChatServer.java | 66+++++++++++++++++++-----------------------------------------------
MSCP.java | 2+-
MSCPException.java | 2+-
DSENG3400 A1 2018 V3.pdf | 0
MTimeDiffException.java | 2+-
8 files changed, 127 insertions(+), 125 deletions(-)

diff --git a/AssessmentItemCoverSheet.pdf b/AssessmentItemCoverSheet.pdf Binary files differ. diff --git a/Chat.java b/Chat.java @@ -4,21 +4,29 @@ import java.io.PrintWriter; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; +import java.util.concurrent.*; +import java.awt.*; +import java.awt.event.*; /** - * Chat.java - SENG3400A1 + * Chat.java * Shared functions and variables between ChatServer and ChatClient * * @author Cody Lewis * @since 2018-08-19 */ -public class Chat { - protected Scanner console; +public class Chat extends Frame { protected PrintWriter out; protected BufferedReader in; protected Socket cliSocket; protected InetAddress address; protected int port; protected String username; + public static final long serialVersionUID = 1L; + protected TextArea msgArea; + protected TextField msgField; + protected boolean disconnect; + protected Thread recvMsg; + private boolean isRecieving; /** * Enum of the various error codes returned by the classes */ @@ -39,37 +47,66 @@ public class Chat { */ public int value() { return code; } } + public Chat() {} /** - * Default Constructor + * Input Constructor */ - public Chat() { - console = new Scanner(System.in); + public Chat(String title) { + disconnect = false; + isRecieving = true; + setLayout(new FlowLayout()); + msgArea = new TextArea(); // use append(String str) to add messages + add(msgArea); + Label lbl = new Label("Message: "); + add(lbl); + msgField = new TextField(30); + add(msgField); + Button msgBtn = new Button("Send"); + add(msgBtn); + msgBtn.addActionListener(new Send()); + Button exitBtn = new Button("Exit"); + add(exitBtn); + exitBtn.addActionListener(new Exit()); + setTitle(title); + setSize(500, 250); + setVisible(true); } - /** - * The chat message rules - * @return A String containing the rules of the chat's messaging - */ - protected String rules() { - return "Press enter twice to send a message,\nType DISCONNECT to end the chat"; + private class Send implements ActionListener { + @Override + public void actionPerformed(ActionEvent evt) { + try { + String message = textToMessage(); + msgArea.append("Waiting for message to send...\n"); + out.println(SCP.message(address.getHostAddress(), port, message)); + msgArea.append("Message Sent: " + message + "\n"); + } catch(Exception e) {} + } + } + protected class Recieve implements Runnable { + private String uname; + public Recieve(String uname) { this.uname = uname; } + public void run() { + try { + while(isRecieving) { + String recievedMessage = recieveMessage(); + if(recievedMessage == "DISCONNECT") { + out.println(SCP.acknowledge()); + msgArea.append("Other user disconnected\n"); + disconnect = true; + } else { + msgArea.append(String.format("%s: %s\n", uname, recievedMessage)); + } + } + } catch(Exception e) {} + } } /** - * Take an input from the users and give an out suitable to put into a message - * @return A String of the input formatted to be embedded in a SCP message + * Loop for sending a recieving messages */ - protected String textToMessage() { - String line = console.nextLine(), message = ""; - boolean empty = true; // Make sure an empty message is not sent - do { - if(line.length() != 0) { - empty = false; - } - if(line.compareTo("DISCONNECT") == 0) { - return "DISCONNECT"; - } - message += "\n" + line; - line = console.nextLine(); - } while(empty || line.length() != 0); - return message.substring(1); // get rid of leading \n + protected void messageLoop() throws SCPException, IOException { + String uname = username == null ? "Client" : "Server"; // a server has null username + recvMsg = new Thread(new Recieve(uname), "scp"); + recvMsg.start(); } /** * Recieve a message from the other user @@ -87,6 +124,32 @@ public class Chat { } return SCP.parseMessage(packet, address.getHostAddress(), port); } + private class Exit implements ActionListener { + @Override + public void actionPerformed(ActionEvent evt) { + try { + // out.println(SCP.disconnect()); + disconnect(); // server side disconnects don't quite work + isRecieving = false; + recvMsg.interrupt(); + disconnect = true; + if(recieveMessage().compareTo("ACKNOWLEDGE") == 0) { // this seems to be the problem + msgArea.append("Successfully disconnected\n"); + } else { + throw new SCPException("Client did not acknowledge disconnect"); + } + } catch(Exception e) { } + } + } + /** + * Take an input from the users and give an out suitable to put into a message + * @return A String of the input formatted to be embedded in a SCP message + */ + protected String textToMessage() { + String message = msgField.getText(); + msgField.setText(""); + return message; + } /** * Send a SCP disconnect to the other user */ diff --git a/ChatClient.java b/ChatClient.java @@ -6,19 +6,20 @@ import java.net.Socket; import java.net.InetAddress; import java.net.UnknownHostException; /** - * ChatClient.java - SENG3400A1 + * ChatClient.java * A socket based half duplex chat client * * @author Cody Lewis * @since 2018-08-10 */ public class ChatClient extends Chat { + public ChatClient(String title) { super(title); } /** * The main thread * @param args command line arguments */ public static void main(String args[]) { - ChatClient cc = new ChatClient(); + ChatClient cc = new ChatClient("SCP Client"); int exitVal = cc.run(args); System.exit(exitVal); } @@ -31,18 +32,18 @@ public class ChatClient extends Chat { try { address = args.length > 0 ? InetAddress.getByName(args[0]) : InetAddress.getLocalHost(); port = args.length > 1 ? Integer.parseInt(args[1]) : 3400; - if(port < 1024) { - throw new SCPException("Using a port number 1023 or lower may interrupt system operations"); - } - System.out.println(String.format("Connecting to %s:%d", address.getHostAddress(), port)); + msgArea.append(String.format("Connecting to %s:%d\n", address.getHostAddress(), port)); connectToServer(); - System.out.println("Connected to server"); - System.out.print("Input a username: "); - username = console.nextLine(); + msgArea.append("Connected to server\n"); + username = args.length > 2 ? args[2] : "Client"; SCPConnect(); - System.out.println("Connected to SCP"); - messageLoop(); - console.close(); + msgArea.append("Connected to SCP\n"); + // System.exit(0); + while(!disconnect) { + messageLoop(); + while(recvMsg.isAlive() || !disconnect); + } + cliSocket.close(); return 0; } catch(SCPException SCPe) { System.err.println("Error: " + SCPe.getMessage()); @@ -54,45 +55,11 @@ public class ChatClient extends Chat { System.err.println("Error: " + ioe.getMessage()); return errorCodes.IOERROR.value(); } catch(NullPointerException npe) { - System.out.println("\nError: unexpected cutoff from Server, ending program"); + System.err.println("\nError: unexpected cutoff from Server, ending program"); return errorCodes.NULLERROR.value(); } } /** - * Loop for sending and recieving messages - */ - private void messageLoop() throws SCPException, IOException, NullPointerException { - String message; - String recievedMessage; - boolean disconnect = false; - while(!disconnect) { - recievedMessage = recieveMessage(); - System.out.println(); - if(recievedMessage == "DISCONNECT") { - out.println(SCP.acknowledge()); - System.out.println("Server disconnected"); - disconnect = true; - break; - } - System.out.print(String.format("Server: %s", recievedMessage)); - System.out.print("Send a message: "); - message = textToMessage(); - if(message.compareTo("DISCONNECT") == 0) { - out.println(SCP.disconnect()); - if(recieveMessage().compareTo("ACKNOWLEDGE") == 0) { - System.out.println("Disconnected from server"); - disconnect = true; - break; - } else { - throw new SCPException("Server did not acknowledge disconnect"); - } - } - System.out.println("Waiting for message to send"); - out.println(SCP.message(address.getHostAddress(), port, message)); - System.out.print("Server is typing..."); - } - } - /** * Connect to the server * @param hostName the name of the server * @param port the port number the server is running on diff --git a/ChatServer.java b/ChatServer.java @@ -6,7 +6,7 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.InetAddress; /** - * ChatServer.java - Seng3400A1 + * ChatServer.java * A socket based half duplex chat server * * @author Cody Lewis @@ -17,12 +17,13 @@ public class ChatServer extends Chat { private String username; private String welcomeMessage; private static final int BACKLOG = 1; // Max length for queue of messages + public ChatServer(String title) { super(title); } /** * The main thread * @param args command line arguments */ public static void main(String args[]) { - ChatServer cs = new ChatServer(); + ChatServer cs = new ChatServer("SCP Server"); int exitVal = cs.run(args); System.exit(exitVal); } @@ -39,9 +40,9 @@ public class ChatServer extends Chat { throw new SCPException("Using a port number 1023 or lower may interrupt system operations"); } welcomeMessage = args.length > 2 ? args[2] : "Welcome to SCP"; - System.out.println(String.format("Starting server on %s:%d", address.getHostAddress(), port)); + msgArea.append(String.format("Starting server on %s:%d\n", address.getHostAddress(), port)); startSocket(); - System.out.println("Started server"); + msgArea.append("Started server\n"); while(true) { hostConnection(); } @@ -58,60 +59,31 @@ public class ChatServer extends Chat { */ private void hostConnection() throws SCPException, IOException { try { - System.out.println("Waiting for client to connect"); + msgArea.append("Waiting for client to connect\n"); acceptClient(); - System.out.println("Client successfully connected"); - System.out.println("Waiting for client to SCP connect"); + msgArea.append("Client successfully connected\n"); + msgArea.append("Waiting for client to SCP connect\n"); username = clientConnect(); username = username.substring(1, username.length() - 1); // remove quotes if(username == "") { // Can't have a blank username anyway cliSocket.close(); - System.out.println("Rejected client for time differential greater than 5, trying again"); + msgArea.append("Rejected client for time differential greater than 5, trying again"); } else { SCPAccept(); if(acknowledged()) { - System.out.println(String.format("User %s has connected to SCP", username)); - System.out.println(); - messageLoop(); + msgArea.append(String.format("User %s has connected to SCP\n\n", username)); + String message = welcomeMessage + "\n"; // send welcome message + chat rules to client + msgArea.append("Waiting for message to send...\n"); + out.println(SCP.message(address.getHostAddress(), port, message)); + msgArea.append("Message Sent: " + message + "\n"); + while(!disconnect) { + messageLoop(); + while(recvMsg.isAlive() || !disconnect); + } } } } catch(NullPointerException npe) { - System.out.println("\nError: unexpected cut-off from client, looking for new client"); - } - } - /** - * Loop for sending a recieving messages - */ - private void messageLoop() throws SCPException, IOException { - String message = welcomeMessage + "\n" + rules() + "\n"; // send welcome message + chat rules to client - String recievedMessage; - boolean disconnect = false; - System.out.println(rules()); - while(!disconnect) { // I assume this gets sigkilled to end - System.out.println("Waiting for message to send"); - out.println(SCP.message(address.getHostAddress(), port, message)); - System.out.print(String.format("%s is typing...", username)); - recievedMessage = recieveMessage(); - System.out.println(); - if(recievedMessage == "DISCONNECT") { - out.println(SCP.acknowledge()); - System.out.println("Client disconnected"); - disconnect = true; - break; - } - System.out.print(String.format("%s: %s", username, recievedMessage)); - System.out.print("Send a message: "); - message = textToMessage(); - if(message.compareTo("DISCONNECT") == 0) { - out.println(SCP.disconnect()); - if(recieveMessage().compareTo("ACKNOWLEDGE") == 0) { - disconnect = true; - System.out.println("Successfully disconnected from Client"); - break; - } else { - throw new SCPException("Client did not acknowledge disconnect"); - } - } + msgArea.append("\nError: unexpected cut-off from client, looking for new client\n"); } } /** diff --git a/SCP.java b/SCP.java @@ -3,7 +3,7 @@ import java.io.BufferedReader; import java.io.StringReader; import java.io.IOException; /** - * SCP.java - Seng3400A1 + * SCP.java * SCP parsing/packet creating library * * @author Cody Lewis diff --git a/SCPException.java b/SCPException.java @@ -1,5 +1,5 @@ /** - * SCPException.java - Seng3400A1 + * SCPException.java * Exception for SCP related errors * * @author Cody Lewis diff --git a/SENG3400 A1 2018 V3.pdf b/SENG3400 A1 2018 V3.pdf Binary files differ. diff --git a/TimeDiffException.java b/TimeDiffException.java @@ -1,5 +1,5 @@ /** - * TimeDiffException.java - Seng3400A1 + * TimeDiffException.java * Exception for the Time Diff error from SCP parsing * * @author Cody Lewis