diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Bavlsik/BavlsikClient.java b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Bavlsik/BavlsikClient.java index 58d93d59eba78180cf461467af0017a01fee7e0f..94fdb5e9a4f38266a166be160b3ac3a896fe3143 100644 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Bavlsik/BavlsikClient.java +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Bavlsik/BavlsikClient.java @@ -12,6 +12,7 @@ import java.util.Scanner; * @author tbavlsik */ public class BavlsikClient { + public final static String LOCALHOST = "0:0:0:0:0:0:0:1"; //Local host /** @@ -21,19 +22,36 @@ public class BavlsikClient { public static void main(String[] args) throws Exception { Socket socket = new Socket(LOCALHOST, 2317); - new Thread(new Reader(socket)).start(); + Thread readerThread = new Thread(new Reader(socket)); + readerThread.start(); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()) { - out.println(scanner.nextLine()); + String msg = scanner.nextLine(); + //If the client wants to exit, type quit and close the socket + if(msg.equalsIgnoreCase("quit")){ + socket.close(); + } + //Checks to see if client or server closed socket, if so, end the program + if (socket.isClosed()) { + System.out.println("Connection closed. Exiting..."); + break; + } + else{ + out.println(msg); + } } + readerThread.join(); } private static class Reader implements Runnable { + private BufferedReader in; + private Socket socket; public Reader(Socket socket) throws IOException { + this.socket = socket; in = new BufferedReader(new InputStreamReader(socket.getInputStream())); } @@ -45,9 +63,15 @@ public class BavlsikClient { System.out.println(message); } } catch (IOException e) { - System.out.println("Error reading from server: " + e); + System.out.println("Disconnected from server."); + } finally { + try { + socket.close(); + } catch (IOException e) { + System.out.println("Error closing socket: " + e); + } } } } - + } diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Bavlsik/BavlsikServer.java b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Bavlsik/BavlsikServer.java index f85726625f3bf3ec0bd29fd59f52f562a67cc2b6..ef4978fbe5e757632f5e05033bfe3286abd1cee7 100644 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Bavlsik/BavlsikServer.java +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Bavlsik/BavlsikServer.java @@ -9,14 +9,18 @@ import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** - * + * This class establishes a passcode protected chat server. Each client that connects + * is handled by a new thread and messages are broadcast to all connected clients. * @author tbavlsik */ public class BavlsikServer { + // the set clientWriters contains form all sockets the active PrintStream private static Set<PrintWriter> clientWriters = new HashSet<>(); @@ -24,25 +28,40 @@ public class BavlsikServer { * @param args the command line arguments */ public static void main(String[] args) { + ArrayList passcodes = new ArrayList<>(Arrays.asList(1, 29, 97));//Very secret passcode, wonder where those numbers came from... System.out.println(BavlsikServer.class.getName() + " has started..."); // it helps debugging to put this on console first - try (ServerSocket listener = new ServerSocket(2317)) { + try (ServerSocket listener = new ServerSocket(2317)) { while (true) { Handler handler = new Handler(listener.accept()); // create a new thread writing and reading to and from the new socket OutputStream os = handler.socket.getOutputStream(); PrintStream ps = new PrintStream(os); - + InetAddress remoteAddress = handler.socket.getInetAddress(); int remotePort = handler.socket.getPort(); + String message = remoteAddress.getHostName() + "=" + remoteAddress.getHostAddress() + ", " + remotePort + " has connected to the server."; System.out.println(message); - ps.println("Welcome " + remoteAddress.getHostName() + "=" + remoteAddress.getHostAddress() + ", " + remotePort + " to the group chat!"); - for (PrintWriter writer : clientWriters) { + BufferedReader reader = new BufferedReader(new InputStreamReader(handler.socket.getInputStream())); + ps.println("Enter a passcode:"); + String passInput = reader.readLine(); // read the entire line as a string + + int pass = Integer.parseInt(passInput.trim()); + + //Validate the client entered passcode + if (passcodes.contains(pass)) { + ps.println("Welcome " + remoteAddress.getHostName() + "=" + remoteAddress.getHostAddress() + ", " + remotePort + " to the group chat!"); + for (PrintWriter writer : clientWriters) { writer.println(message); } - ps.flush(); - handler.start(); + ps.flush(); + handler.start(); + } else {//Kick the client from the server. + ps.println("Not a valid passcode."); + System.out.println(remoteAddress.getHostName() + "=" + remoteAddress.getHostAddress() + ", " + remotePort + " entered an incorrect passcode; disconnecting."); + handler.socket.close(); + } } - }catch (IOException e) { + } catch (IOException e) { System.err.println("Problem with " + BavlsikServer.class.getName() + " networking: " + e); // Provide more helpful information to user if exception occurs due to running twice at one time @@ -50,10 +69,11 @@ public class BavlsikServer { System.err.println("*** Be sure to stop any other running instances of programs using this port!"); } } - + } - + private static class Handler extends Thread { + public final Socket socket; private PrintWriter out; private BufferedReader in; @@ -71,10 +91,10 @@ public class BavlsikServer { synchronized (clientWriters) { clientWriters.add(out); } - + //Read in the message sent by the client and then send it to all other connected clients String message; while ((message = in.readLine()) != null) { - String outputMessage = socket.getInetAddress().getHostName() + "=" + socket.getInetAddress().getHostAddress() + ", " + socket.getPort()+ ": " + message; + String outputMessage = socket.getInetAddress().getHostName() + "=" + socket.getInetAddress().getHostAddress() + ", " + socket.getPort() + ": " + message; System.out.println(outputMessage); for (PrintWriter writer : clientWriters) { writer.println(outputMessage); @@ -83,6 +103,9 @@ public class BavlsikServer { } catch (IOException e) { System.out.println("Error handling client: " + e); } finally { + //if a client disconnects or is kicked from the server, close the socket and broadcast the message to the chat + String disconnectMessage = (socket.getInetAddress().getHostName() + "=" + socket.getInetAddress().getHostAddress() + ", " + socket.getPort() + " has disconnected."); + System.out.println(disconnectMessage); try { socket.close(); } catch (IOException e) { @@ -92,8 +115,11 @@ public class BavlsikServer { synchronized (clientWriters) { clientWriters.remove(out); } + for (PrintWriter writer : clientWriters) { + writer.println(disconnectMessage); + } } } } - + } diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Bavlsik/README.md b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Bavlsik/README.md index 867191babbb74e9d2677211dd49749d6e0b85f91..448a0bf1e467203f8eb4e28081fbf90944d841f2 100644 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Bavlsik/README.md +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Bavlsik/README.md @@ -3,8 +3,18 @@ *** ## Description -Modification of TcpExample3 and adding some code to implement a chat room with multiple clients. +Modification of TcpExample3 and adding some code to implement a passcode protected +chat room with multiple clients. -The 'BavlsikServer' class sets up a server that listens for incoming client connections on port 2317. When a client connects, the server creates a new handler thread for managing communication with that client. Each client's messages are broadcast to all other connected clients. +The 'BavlsikServer' class sets up a server that listens for incoming client connections +on port 2317. When a client connects, the server creates a new handler thread for +managing communication with that client. After the connection is established, +the server prompts the client for a passcode. If the client enters a valid passcode +they are added to teh chat room where each client's messages are broadcast to all +other connected clients. If the passcode is entered incorrectly, they client is +disconnected from the server. If a client enters 'quit' they disconnect from the server. -The 'BavlsikClient' class connects to a server running on localhost at port 2317. It sends user input from the console to the server and displays messages received from the server. \ No newline at end of file +The 'BavlsikClient' class connects to a server running on localhost at port 2317. +If the client enters a correct passcode, they are added to the chatroom, if it is +incorrect they are disconnecte. The client then sends user input from the console +to the server and displays messages received from the server. \ No newline at end of file