From d026a5a3607968ca429767cd02db0e8dc911a427 Mon Sep 17 00:00:00 2001 From: Azeb Tesfay Date: Fri, 5 Dec 2025 11:43:30 -0800 Subject: [PATCH 1/7] Commiting Wave 2: Argument Parsing --- src/ChatterboxClient.java | 128 ++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 47 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 9f80fc0..57a39f7 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.Scanner; @@ -11,18 +12,19 @@ * * Protocol summary (what the server expects): * 1) Client connects via TCP to host:port. - * 2) Server sends a prompt asking for "Please enter your username and password, separated by a space". + * 2) Server sends a prompt asking for "Please enter your username and password, + * separated by a space". * 3) Client sends ONE LINE containing: username + space + password + newline. * 4) Server responds with either: - * - a line starting with the word "Welcome" (success), or - * - an error line (failure), then closes the connection. + * - a line starting with the word "Welcome" (success), or + * - an error line (failure), then closes the connection. * 5) After success, the client: - * - prints any incoming server messages to the user output - * - reads user input and sends each line to the server + * - prints any incoming server messages to the user output + * - reads user input and sends each line to the server * * Important design constraint: * - Do NOT read/write directly from System.in/System.out inside helper methods. - * Always use userInput/userOutput instead. + * Always use userInput/userOutput instead. */ public class ChatterboxClient { @@ -43,10 +45,11 @@ public class ChatterboxClient { * Program entry. * * Expected command-line usage: - * javac src/*.java && java -cp src ChatterboxClient HOST PORT USERNAME PASSWORD + * javac src/*.java && java -cp src ChatterboxClient HOST PORT USERNAME PASSWORD * * Example: - * javac src/*.java && java -cp src ChatterboxClient localhost 12345 sharon abc123 + * javac src/*.java && java -cp src ChatterboxClient localhost 12345 sharon + * abc123 * * This method is already complete. Your work is in the TODO methods below. */ @@ -59,24 +62,25 @@ public static void main(String[] args) { } catch (IllegalArgumentException e) { System.err.println("Error parsing arguments"); System.err.println(e.getMessage()); - System.err.println("Usage: javac src/*.java && java -cp src ChatterboxClient HOST PORT USERNAME PASSWORD"); + System.err.println( + "Usage: javac src/*.java && java -cp src ChatterboxClient HOST PORT USERNAME PASSWORD"); System.exit(1); - } + } System.out.println("Read options: " + options.toString()); System.out.println("Creating client..."); - + ChatterboxClient client = new ChatterboxClient(options, System.in, System.out); System.out.println("Client created: " + client.toString()); System.out.println("Connecting to server..."); try { client.connect(); - } catch(IOException e) { + } catch (IOException e) { System.err.println("Failed to connect to server"); System.err.println(e.getMessage()); System.exit(1); - } + } System.out.println("Connected to server"); System.out.println("Authenticating..."); @@ -90,7 +94,7 @@ public static void main(String[] args) { System.err.println("Failed authentication"); System.err.println(e.getMessage()); System.exit(1); - } + } System.out.println("Finished authentication"); System.out.println("Beginning chat streaming"); @@ -100,9 +104,8 @@ public static void main(String[] args) { System.err.println("Error streaming chats"); System.err.println(e.getMessage()); System.exit(1); - } - } - catch (UnsupportedOperationException e) { + } + } catch (UnsupportedOperationException e) { System.err.println(e.getMessage()); } } @@ -111,10 +114,10 @@ public static void main(String[] args) { * Parse command-line arguments into a ChatterboxOptions object. * * Required argument order: - * HOST - * PORT - * USERNAME - * PASSWORD + * HOST + * PORT + * USERNAME + * PASSWORD * * Rules: * - If args.length != 4, throw IllegalArgumentException. @@ -125,9 +128,31 @@ public static void main(String[] args) { * @throws IllegalArgumentException on any bad/missing input */ public static ChatterboxOptions parseArgs(String[] args) throws IllegalArgumentException { - // TODO: read args in the required order and return new ChatterboxOptions(host, port, username, password) + + // 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"); + + ChatterboxOptions chatterboxOptions = new ChatterboxOptions(args[0], + Integer.parseInt(args[1]), args[2], args[3]); + + // - If args.length != 4, throw IllegalArgumentException. + if (args.length != 4) { + throw new IllegalArgumentException("Require host, port, username, password"); + } + // - PORT must parse as an integer in the range 1..65535, else throw. + String portString = args[1]; + int port = Integer.parseInt(portString); + + if (port < 1 || port > 65535) { + throw new IllegalArgumentException("Port must be in the range 1..65535"); + + } + return chatterboxOptions; + + // throw new UnsupportedOperationException( + // "Argument parsing not yet implemented. Implement parseArgs and remove this + // exception"); } /** @@ -138,16 +163,18 @@ public static ChatterboxOptions parseArgs(String[] args) throws IllegalArgumentE * - Copy host/port/username/password from options into fields. * - Do NOT open sockets or talk to the network here. That's connect(). * - * @param options parsed connection/auth settings - * @param userInput stream to read user-typed data from + * @param options parsed connection/auth settings + * @param userInput stream to read user-typed data from * @param userOutput stream to print data to the user */ public ChatterboxClient(ChatterboxOptions options, InputStream userInput, OutputStream userOutput) { 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 + throw new UnsupportedOperationException( + "Constructor not yet implemented. Implement ChatterboxClient constructor and remove this exception"); + // TODO: copy options.getHost(), getPort(), getUsername(), getPassword() into + // fields } /** @@ -164,10 +191,13 @@ 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!"); + throw new UnsupportedOperationException( + "Connect not yet implemented. Implement connect() and remove this exception!"); - // 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 + // 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 } /** @@ -175,41 +205,45 @@ public void connect() throws IOException { * * Responsibilities: * - Read and display the server's initial prompt line (if any) - * to userOutput. + * to userOutput. * - Send ONE LINE containing: - * username + " " + password + "\n" - * using serverOutput. + * username + " " + password + "\n" + * using serverOutput. * - Read ONE response line from serverReader. * - If the response indicates failure, throw IllegalArgumentException - * with that response text. + * with that response text. * - If success, print the welcome line(s) to userOutput and return. * * Assumption: * - The server closes the connection after a failed auth. * - * @throws IOException for network errors + * @throws IOException for network errors * @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 + 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 // send messages using serverWriter (don't forget to flush!) } /** - * Start full-duplex chat streaming. SEE INSTRUCTIONS FOR HOW TO DO THIS PART BY PART + * Start full-duplex chat streaming. SEE INSTRUCTIONS FOR HOW TO DO THIS PART BY + * PART * * Responsibilities: * - Run printIncomingChats() and sendOutgoingChats() in separate threads. * * Tip: * - Make printIncomingChats() work (single-threaded) before worrying about - * sendOutgoingChats() and threading. + * sendOutgoingChats() and threading. * * @throws IOException */ public void streamChat() throws IOException { - throw new UnsupportedOperationException("Chat streaming not yet implemented. Implement streamChat() and remove this exception!"); + throw new UnsupportedOperationException( + "Chat streaming not yet implemented. Implement streamChat() and remove this exception!"); } /** @@ -217,14 +251,14 @@ public void streamChat() throws IOException { * * Responsibilities: * - Loop: - * readLine() from server - * if null -> server disconnected, exit program - * else write that line to userOutput + * readLine() from server + * if null -> server disconnected, exit program + * else write that line to userOutput * * Notes: * - Do NOT use System.out directly. * - If an IOException happens, treat it as disconnect: - * print a message to userOutput and exit. + * print a message to userOutput and exit. */ public void printIncomingChats() { // Listen on serverReader @@ -236,12 +270,12 @@ public void printIncomingChats() { * * Responsibilities: * - Loop forever: - * if scanner has a next line, read it - * write it to serverOutput + newline + flush + * if scanner has a next line, read it + * write it to serverOutput + newline + flush * * Notes: * - If writing fails (IOException), the connection is gone: - * print a message to userOutput and exit. + * print a message to userOutput and exit. */ public void sendOutgoingChats() { // Use the userInput to read, NOT System.in directly From be962cafed6a2c9645668b026a93cf44dd1f61b5 Mon Sep 17 00:00:00 2001 From: Azeb Tesfay Date: Fri, 5 Dec 2025 13:33:31 -0800 Subject: [PATCH 2/7] Commiting Wave 3: Client Constructor --- src/ChatterboxClient.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 57a39f7..801387a 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -171,10 +171,16 @@ 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"); + // throw new UnsupportedOperationException( + // "Constructor not yet implemented. Implement ChatterboxClient constructor and + // remove this exception"); // TODO: copy options.getHost(), getPort(), getUsername(), getPassword() into // fields + this.host = options.getHost(); + this.port = options.getPort(); + this.username = options.getUsername(); + this.password = options.getPassword(); + } /** From 47490722cafb1f967e306c0de8da71ff6099d117 Mon Sep 17 00:00:00 2001 From: Azeb Tesfay Date: Fri, 5 Dec 2025 14:31:43 -0800 Subject: [PATCH 3/7] COmmit for wave 4 Connect --- src/ChatterboxClient.java | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 801387a..e636b6d 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -2,7 +2,9 @@ import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.Scanner; @@ -197,8 +199,22 @@ 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(host, port)) { + InputStream inputStream = socket.getInputStream(); + InputStreamReader inputStreamReader = new InputStreamReader(inputStream, + java.nio.charset.StandardCharsets.UTF_8); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + + OutputStream outputStream = socket.getOutputStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, + java.nio.charset.StandardCharsets.UTF_8); + BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter); + + this.serverReader = bufferedReader; + this.serverWriter = bufferedWriter; + + } // Make sure to have this.serverReader and this.serverWriter set by the end of // this method! From 3ab61870cbcc8d387f48f93d66e6dd1afb8eae4c Mon Sep 17 00:00:00 2001 From: Azeb Tesfay Date: Sun, 7 Dec 2025 10:15:31 -0800 Subject: [PATCH 4/7] commiting wave 5 Implement Authenticate method make the client send user and password with space ended with newline --- src/ChatterboxClient.java | 46 +++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index e636b6d..b96d989 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -200,28 +200,27 @@ public ChatterboxClient(ChatterboxOptions options, InputStream userInput, Output */ public void connect() throws IOException { - try (Socket socket = new Socket(host, port)) { - InputStream inputStream = socket.getInputStream(); - InputStreamReader inputStreamReader = new InputStreamReader(inputStream, - java.nio.charset.StandardCharsets.UTF_8); - BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + Socket socket = new Socket(host, port); + InputStream inputStream = socket.getInputStream(); + InputStreamReader inputStreamReader = new InputStreamReader(inputStream, + java.nio.charset.StandardCharsets.UTF_8); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader); - OutputStream outputStream = socket.getOutputStream(); - OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, - java.nio.charset.StandardCharsets.UTF_8); - BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter); + OutputStream outputStream = socket.getOutputStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, + java.nio.charset.StandardCharsets.UTF_8); + BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter); - this.serverReader = bufferedReader; - this.serverWriter = bufferedWriter; + this.serverReader = bufferedReader; + this.serverWriter = bufferedWriter; - } - - // 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 } + // 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 + /** * Authenticate with the server using the simple protocol. * @@ -243,8 +242,17 @@ 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!"); + + String serverPrompt = serverReader.readLine(); + System.out.println(serverPrompt); + + serverWriter.write(username + " " + password); + serverWriter.newLine(); + serverWriter.flush(); + + String responseReader = serverReader.readLine(); + System.out.println(responseReader); + // Hint: use the username/password instance variables, DO NOT READ FROM // userInput // send messages using serverWriter (don't forget to flush!) From 1dd543c83cea448707d4bb31987c70485a6f7386 Mon Sep 17 00:00:00 2001 From: Azeb Tesfay Date: Mon, 8 Dec 2025 12:06:07 -0800 Subject: [PATCH 5/7] Commit for Wave 6: Print Incoming --- src/ChatterboxClient.java | 50 ++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index b96d989..c6d4fdb 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -6,6 +6,7 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; +import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.util.Scanner; @@ -204,15 +205,12 @@ public void connect() throws IOException { InputStream inputStream = socket.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, java.nio.charset.StandardCharsets.UTF_8); - BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + this.serverReader = new BufferedReader(inputStreamReader); OutputStream outputStream = socket.getOutputStream(); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, java.nio.charset.StandardCharsets.UTF_8); - BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter); - - this.serverReader = bufferedReader; - this.serverWriter = bufferedWriter; + this.serverWriter = new BufferedWriter(outputStreamWriter); } @@ -272,8 +270,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!"); + printIncomingChats(); + } /** @@ -290,9 +288,31 @@ public void streamChat() throws IOException { * - If an IOException happens, treat it as disconnect: * print a message to userOutput and exit. */ - public void printIncomingChats() { + + /*** + * + * OutputStream outputStream = socket.getOutputStream(); + * OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, + * java.nio.charset.StandardCharsets.UTF_8); + * this.serverWriter = new BufferedWriter(outputStreamWriter); + * + * @throws IOException + * + */ + public void printIncomingChats() throws IOException { // Listen on serverReader // Write to userOutput, NOT System.out + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(userOutput, + java.nio.charset.StandardCharsets.UTF_8); + this.serverWriter = new BufferedWriter(outputStreamWriter); + String line; + while ((line = serverReader.readLine()) != null) { + serverWriter.write(line); + serverWriter.newLine(); + serverWriter.flush(); + + } + } /** @@ -307,10 +327,22 @@ public void printIncomingChats() { * - If writing fails (IOException), the connection is gone: * print a message to userOutput and exit. */ - public void sendOutgoingChats() { + + /*** + * InputStream inputStream = socket.getInputStream(); + * InputStreamReader inputStreamReader = new InputStreamReader(inputStream, + * java.nio.charset.StandardCharsets.UTF_8); + * this.serverReader = new BufferedReader(inputStreamReader); + * + * @throws IOException + * @throws UnknownHostException + * + */ + public void sendOutgoingChats() throws UnknownHostException, IOException { // Use the userInput to read, NOT System.in directly // loop forever reading user input // write to serverOutput + } public String getHost() { From c83fb38b3fd3edfe95f3ae5bce4221e1fe889d99 Mon Sep 17 00:00:00 2001 From: Azeb Tesfay Date: Mon, 8 Dec 2025 12:36:51 -0800 Subject: [PATCH 6/7] Commit forr wave 6 create a new bufferwriter --- src/ChatterboxClient.java | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index c6d4fdb..b100cac 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -304,12 +304,12 @@ public void printIncomingChats() throws IOException { // Write to userOutput, NOT System.out OutputStreamWriter outputStreamWriter = new OutputStreamWriter(userOutput, java.nio.charset.StandardCharsets.UTF_8); - this.serverWriter = new BufferedWriter(outputStreamWriter); + BufferedWriter nBufferedWriter = new BufferedWriter(outputStreamWriter); String line; while ((line = serverReader.readLine()) != null) { - serverWriter.write(line); - serverWriter.newLine(); - serverWriter.flush(); + nBufferedWriter.write(line); + nBufferedWriter.newLine(); + nBufferedWriter.flush(); } @@ -342,6 +342,18 @@ public void sendOutgoingChats() throws UnknownHostException, IOException { // Use the userInput to read, NOT System.in directly // loop forever reading user input // write to serverOutput + Socket socket = new Socket(host, port); + socket.getOutputStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(userOutput, + java.nio.charset.StandardCharsets.UTF_8); + this.serverWriter = new BufferedWriter(outputStreamWriter); + String line; + while ((line = serverReader.readLine()) != null) { + serverWriter.write(line); + serverWriter.newLine(); + serverWriter.flush(); + + } } From cb4747699481bae52d00bd3ef5ad7b46f284a1a8 Mon Sep 17 00:00:00 2001 From: Azeb Tesfay Date: Mon, 8 Dec 2025 14:05:35 -0800 Subject: [PATCH 7/7] Commit wave 7 --- src/ChatterboxClient.java | 40 ++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index b100cac..2900eeb 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -53,6 +53,9 @@ public class ChatterboxClient { * Example: * javac src/*.java && java -cp src ChatterboxClient localhost 12345 sharon * abc123 + * + * javac src/*.java && java -cp src ChatterboxClient localhost 12345 sharon + * abc123 * * This method is already complete. Your work is in the TODO methods below. */ @@ -270,7 +273,26 @@ public void authenticate() throws IOException, IllegalArgumentException { * @throws IOException */ public void streamChat() throws IOException { - printIncomingChats(); + // printIncomingChats(); + // sendOutgoingChats(); + Thread thread1 = new Thread(() -> { + try { + printIncomingChats(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + }); + Thread thread2 = new Thread(() -> { + try { + sendOutgoingChats(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + }); + thread1.start(); + thread2.start(); } @@ -328,13 +350,9 @@ public void printIncomingChats() throws IOException { * print a message to userOutput and exit. */ - /*** - * InputStream inputStream = socket.getInputStream(); - * InputStreamReader inputStreamReader = new InputStreamReader(inputStream, - * java.nio.charset.StandardCharsets.UTF_8); - * this.serverReader = new BufferedReader(inputStreamReader); - * + /* * @throws IOException + * * @throws UnknownHostException * */ @@ -342,13 +360,9 @@ public void sendOutgoingChats() throws UnknownHostException, IOException { // Use the userInput to read, NOT System.in directly // loop forever reading user input // write to serverOutput - Socket socket = new Socket(host, port); - socket.getOutputStream(); - OutputStreamWriter outputStreamWriter = new OutputStreamWriter(userOutput, - java.nio.charset.StandardCharsets.UTF_8); - this.serverWriter = new BufferedWriter(outputStreamWriter); + String line; - while ((line = serverReader.readLine()) != null) { + while ((line = userInput.nextLine()) != null) { serverWriter.write(line); serverWriter.newLine(); serverWriter.flush();