From c6d07ba9635442c81d7b33ba731e7d52603ccfe2 Mon Sep 17 00:00:00 2001 From: allenres Date: Sun, 7 Dec 2025 14:07:40 -0800 Subject: [PATCH 1/7] parseArgs, wave 2 complete --- src/ChatterboxClient.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 9f80fc0..ac9904a 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -127,7 +127,20 @@ public static void main(String[] args) { public static ChatterboxOptions parseArgs(String[] args) throws IllegalArgumentException { // TODO: read args in the required order and return new ChatterboxOptions(host, port, username, password) // Remove this exception - throw new UnsupportedOperationException("Argument parsing not yet implemented. Implement parseArgs and remove this exception"); + if (args.length != 4) { + throw new IllegalArgumentException(); + } + + int port = Integer.parseInt(args[1]); + ChatterboxOptions options; + + if (port >= 1 && port <= 65535) { + options = new ChatterboxOptions(args[0], port, args[2], args[3]); + } else { + throw new IllegalArgumentException("PORT must be in the range 1..65535"); + } + + return options; } /** From 5bfd1988cbeaea36951179c844c4d0ef79f63186 Mon Sep 17 00:00:00 2001 From: allenres Date: Sun, 7 Dec 2025 14:20:09 -0800 Subject: [PATCH 2/7] create client constructor, wave 3 done --- src/ChatterboxClient.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index ac9904a..7812696 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -1,5 +1,6 @@ import java.io.BufferedReader; import java.io.BufferedWriter; +import java.io.CharArrayReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -126,9 +127,8 @@ public static void main(String[] args) { */ public static ChatterboxOptions parseArgs(String[] args) throws IllegalArgumentException { // TODO: read args in the required order and return new ChatterboxOptions(host, port, username, password) - // Remove this exception if (args.length != 4) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("There must be exactly 4 arguments. Please try again."); } int port = Integer.parseInt(args[1]); @@ -159,8 +159,8 @@ public ChatterboxClient(ChatterboxOptions options, InputStream userInput, Output this.userInput = new Scanner(userInput, StandardCharsets.UTF_8); this.userOutput = userOutput; - throw new UnsupportedOperationException("Constructor not yet implemented. Implement ChatterboxClient constructor and remove this exception"); // TODO: copy options.getHost(), getPort(), getUsername(), getPassword() into fields + options = new ChatterboxOptions(options.getHost(), options.getPort(), options.getUsername(), options.getPassword()); } /** From 78727ac8b6ad825da9960a97bf4ab4c7d96955d4 Mon Sep 17 00:00:00 2001 From: allenres Date: Sun, 7 Dec 2025 17:07:10 -0800 Subject: [PATCH 3/7] fix issue with creating client --- src/ChatterboxClient.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 7812696..7b88b34 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -3,7 +3,11 @@ import java.io.CharArrayReader; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.ServerSocket; +import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.Scanner; @@ -160,7 +164,10 @@ public ChatterboxClient(ChatterboxOptions options, InputStream userInput, Output this.userOutput = userOutput; // TODO: copy options.getHost(), getPort(), getUsername(), getPassword() into fields - options = new ChatterboxOptions(options.getHost(), options.getPort(), options.getUsername(), options.getPassword()); + this.host = options.getHost(); + this.port = options.getPort(); + this.username = options.getUsername(); + this.password = options.getPassword(); } /** @@ -177,8 +184,15 @@ public ChatterboxClient(ChatterboxOptions options, InputStream userInput, Output * @throws IOException if the socket cannot be opened */ public void connect() throws IOException { - throw new UnsupportedOperationException("Connect not yet implemented. Implement connect() and remove this exception!"); + // try (Socket socket = new Socket(getHost(), getPort())) { + // InputStream inputStream = socket.getInputStream(); + // InputStreamReader inputStreamReader = new InputStreamReader(inputStream, java.nio.charset.StandardCharsets.UTF_8); + // this.serverReader = new BufferedReader(inputStreamReader); + // OutputStream outputStream = socket.getOutputStream(); + // OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, java.nio.charset.StandardCharsets.UTF_8); + // this.serverWriter = new BufferedWriter(outputStreamWriter); + // } // Make sure to have this.serverReader and this.serverWriter set by the end of this method! // hint: get the streams from the sockets, use those to create the InputStreamReader/OutputStreamWriter and the BufferedReader/BufferedWriter } From 11c0c1542cccb4aa9143e5ed3c5f59b9b3fbf72e Mon Sep 17 00:00:00 2001 From: allenres Date: Sun, 7 Dec 2025 17:10:25 -0800 Subject: [PATCH 4/7] complete wave 4, connection --- src/ChatterboxClient.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 7b88b34..0d25deb 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -184,15 +184,15 @@ public ChatterboxClient(ChatterboxOptions options, InputStream userInput, Output * @throws IOException if the socket cannot be opened */ public void connect() throws IOException { - // try (Socket socket = new Socket(getHost(), getPort())) { - // InputStream inputStream = socket.getInputStream(); - // InputStreamReader inputStreamReader = new InputStreamReader(inputStream, java.nio.charset.StandardCharsets.UTF_8); - // this.serverReader = new BufferedReader(inputStreamReader); + try (Socket socket = new Socket(getHost(), getPort())) { + InputStream inputStream = socket.getInputStream(); + InputStreamReader inputStreamReader = new InputStreamReader(inputStream, java.nio.charset.StandardCharsets.UTF_8); + this.serverReader = new BufferedReader(inputStreamReader); - // OutputStream outputStream = socket.getOutputStream(); - // OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, java.nio.charset.StandardCharsets.UTF_8); - // this.serverWriter = new BufferedWriter(outputStreamWriter); - // } + OutputStream outputStream = socket.getOutputStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, java.nio.charset.StandardCharsets.UTF_8); + this.serverWriter = new BufferedWriter(outputStreamWriter); + } // Make sure to have this.serverReader and this.serverWriter set by the end of this method! // hint: get the streams from the sockets, use those to create the InputStreamReader/OutputStreamWriter and the BufferedReader/BufferedWriter } From da913b30abd30c787fdd466468b988e8e23ed4ae Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 8 Dec 2025 13:45:30 -0800 Subject: [PATCH 5/7] fix connect method, complete auth method --- src/ChatterboxClient.java | 49 ++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 0d25deb..e1e6e9a 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -131,13 +131,17 @@ public static void main(String[] args) { */ public static ChatterboxOptions parseArgs(String[] args) throws IllegalArgumentException { // TODO: read args in the required order and return new ChatterboxOptions(host, port, username, password) + // handle bad argument count if (args.length != 4) { throw new IllegalArgumentException("There must be exactly 4 arguments. Please try again."); } + // parse port from string to int int port = Integer.parseInt(args[1]); + // initialize options variable ChatterboxOptions options; + // validate port range if (port >= 1 && port <= 65535) { options = new ChatterboxOptions(args[0], port, args[2], args[3]); } else { @@ -184,15 +188,18 @@ public ChatterboxClient(ChatterboxOptions options, InputStream userInput, Output * @throws IOException if the socket cannot be opened */ public void connect() throws IOException { - try (Socket socket = new Socket(getHost(), getPort())) { - InputStream inputStream = socket.getInputStream(); - InputStreamReader inputStreamReader = new InputStreamReader(inputStream, java.nio.charset.StandardCharsets.UTF_8); - this.serverReader = new BufferedReader(inputStreamReader); + // create a socket to host:port + Socket socket = new Socket(host, port); + + // populate serverReader and serverWriter from the socket + InputStream inputStream = socket.getInputStream(); + InputStreamReader inputStreamReader = new InputStreamReader(inputStream, java.nio.charset.StandardCharsets.UTF_8); + this.serverReader = new BufferedReader(inputStreamReader); - OutputStream outputStream = socket.getOutputStream(); - OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, java.nio.charset.StandardCharsets.UTF_8); - this.serverWriter = new BufferedWriter(outputStreamWriter); - } + OutputStream outputStream = socket.getOutputStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, java.nio.charset.StandardCharsets.UTF_8); + this.serverWriter = new BufferedWriter(outputStreamWriter); + // Make sure to have this.serverReader and this.serverWriter set by the end of this method! // hint: get the streams from the sockets, use those to create the InputStreamReader/OutputStreamWriter and the BufferedReader/BufferedWriter } @@ -218,9 +225,33 @@ public void connect() throws IOException { * @throws IllegalArgumentException for bad credentials / server rejection */ public void authenticate() throws IOException, IllegalArgumentException { - throw new UnsupportedOperationException("Authenticate not yet implemented. Implement authenticate() and remove this exception!"); // Hint: use the username/password instance variables, DO NOT READ FROM userInput + // read the server's initial prompt line + String prompt = serverReader.readLine(); + // display the server's prompt line (if any) + if (prompt != null) { + userOutput.write((prompt + "\n").getBytes(StandardCharsets.UTF_8)); + } + + // initialize credentials string + String credentials = username + " " + password + "\n"; // send messages using serverWriter (don't forget to flush!) + // send credentials to server using serverWriter + serverWriter.write(credentials); + serverWriter.flush(); + + // read one response line from serverReader + String response = serverReader.readLine(); + + // handle the response + if (response == null) { + throw new IllegalArgumentException("Server closed the connection after failed authentication."); + } else if (response.startsWith("Welcome")) { // starts w/ welcome = auth success + // print the welcome line to userOutput + userOutput.write((response + "\n").getBytes(StandardCharsets.UTF_8)); + } else { + throw new IllegalArgumentException(response); + } } /** From 0184fca881d850157f9c456a4a1a38bb0b5e15a7 Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 8 Dec 2025 14:06:28 -0800 Subject: [PATCH 6/7] complete wave 6, print incoming --- src/ChatterboxClient.java | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index e1e6e9a..5ac8537 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -199,7 +199,7 @@ public void connect() throws IOException { OutputStream outputStream = socket.getOutputStream(); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, java.nio.charset.StandardCharsets.UTF_8); this.serverWriter = new BufferedWriter(outputStreamWriter); - + // Make sure to have this.serverReader and this.serverWriter set by the end of this method! // hint: get the streams from the sockets, use those to create the InputStreamReader/OutputStreamWriter and the BufferedReader/BufferedWriter } @@ -249,6 +249,7 @@ public void authenticate() throws IOException, IllegalArgumentException { } else if (response.startsWith("Welcome")) { // starts w/ welcome = auth success // print the welcome line to userOutput userOutput.write((response + "\n").getBytes(StandardCharsets.UTF_8)); + return; } else { throw new IllegalArgumentException(response); } @@ -267,7 +268,8 @@ public void authenticate() throws IOException, IllegalArgumentException { * @throws IOException */ public void streamChat() throws IOException { - throw new UnsupportedOperationException("Chat streaming not yet implemented. Implement streamChat() and remove this exception!"); + Thread incomingThread = new Thread(() -> printIncomingChats()); + incomingThread.start(); } /** @@ -287,6 +289,27 @@ public void streamChat() throws IOException { public void printIncomingChats() { // Listen on serverReader // Write to userOutput, NOT System.out + + // loop + try { + String line; + while ((line = serverReader.readLine()) != null) { // through each line from serverReader + // write that line to userOutput + userOutput.write((line + "\n").getBytes(StandardCharsets.UTF_8)); + } + // if null, server is disconnected + userOutput.write(("Server disconnected.\n").getBytes(StandardCharsets.UTF_8)); + // exit program + System.exit(1); + } catch (IOException e) { + // treat as disconnect + try { + // print a message to userOutput + userOutput.write(("Lost connection to server: " + e.getMessage() + "\n").getBytes(StandardCharsets.UTF_8)); + // and exit + System.exit(1); + } catch (IOException i) {} + } } /** From a16786ff7f9f26a583b757fe1f39432dff5ef4f5 Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 8 Dec 2025 14:19:36 -0800 Subject: [PATCH 7/7] wave 7 complete, send outgoing --- src/ChatterboxClient.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 5ac8537..0cc0d7f 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -249,7 +249,7 @@ public void authenticate() throws IOException, IllegalArgumentException { } else if (response.startsWith("Welcome")) { // starts w/ welcome = auth success // print the welcome line to userOutput userOutput.write((response + "\n").getBytes(StandardCharsets.UTF_8)); - return; + return; // return } else { throw new IllegalArgumentException(response); } @@ -270,6 +270,8 @@ public void authenticate() throws IOException, IllegalArgumentException { public void streamChat() throws IOException { Thread incomingThread = new Thread(() -> printIncomingChats()); incomingThread.start(); + Thread outgoingThread = new Thread(() -> sendOutgoingChats()); + outgoingThread.start(); } /** @@ -325,6 +327,21 @@ public void printIncomingChats() { * print a message to userOutput and exit. */ public void sendOutgoingChats() { + while (userInput.hasNext()) { // loop while scanner has a next line + String line = userInput.nextLine(); // read the next line + + try { + // write it to serverReader (serverOutput) + serverWriter.write(line + "\n"); + serverWriter.flush(); + } catch (IOException e) { // if writing fails + // connection is gone + try { + userOutput.write(("Connection is gone: " + e.getMessage() + "\n").getBytes(StandardCharsets.UTF_8)); + } catch (IOException i) {} + System.exit(1); // exit + } + } // Use the userInput to read, NOT System.in directly // loop forever reading user input // write to serverOutput