From fe4cf86492ded2c005995743bfd072549842c361 Mon Sep 17 00:00:00 2001 From: brutzman <brutzman@nps.edu> Date: Sun, 11 Aug 2024 16:07:21 -0700 Subject: [PATCH] ready for final checking --- .../TcpExamples/TcpSentryScenarioClient.java | 100 +++++++++++------- .../TcpSentryScenarioDispatchServer.java | 32 +++--- .../TcpSentryScenarioHandlerThread.java | 86 ++++++++++----- 3 files changed, 133 insertions(+), 85 deletions(-) diff --git a/examples/src/TcpExamples/TcpSentryScenarioClient.java b/examples/src/TcpExamples/TcpSentryScenarioClient.java index 20f7fde618..4ec04abb2e 100644 --- a/examples/src/TcpExamples/TcpSentryScenarioClient.java +++ b/examples/src/TcpExamples/TcpSentryScenarioClient.java @@ -2,6 +2,7 @@ package TcpExamples; import static TcpExamples.TcpSentryScenarioHandlerThread.HALT_WHO_GOES_THERE; import static TcpExamples.TcpSentryScenarioHandlerThread.HOLD_IT_RIGHT_THERE; +import static TcpExamples.TcpSentryScenarioHandlerThread.SENTRY_WATCH_PRESENT; import static TcpExamples.TcpSentryScenarioHandlerThread.YOU_MAY_PASS; import java.io.*; import java.net.*; @@ -27,12 +28,12 @@ import java.net.*; */ public class TcpSentryScenarioClient { - static String prefix = "[" + TcpSentryScenarioClient.class.getName() + "] "; + static String prefix = "[client] "; /** Default constructor */ public TcpSentryScenarioClient() { - // default constructor + // no action needed here } static String DESTINATION_HOST = "localhost"; static int MAX_LOOP_COUNT = 6; @@ -42,12 +43,15 @@ public class TcpSentryScenarioClient * @param args command-line arguments */ public static void main(String[] args) { - try { - System.out.println(prefix + " start, loop " + MAX_LOOP_COUNT + " times"); - System.out.println("======================================================="); + try + { + System.out.println("==============================================================================="); + System.out.println(prefix + "startup, menu 1h.TcpSentryClient, " + TcpSentryScenarioClient.class.getName()); + System.out.println(prefix + "up to " + MAX_LOOP_COUNT + " visitors may approach."); + System.out.println("==============================================================================="); for (int loopCount = 1; loopCount <= MAX_LOOP_COUNT; loopCount++) // loop then exit { - System.out.println(prefix + " creating new socket #" + loopCount + "..."); + System.out.println(prefix + "creating client side to connect new socket #" + loopCount + "..."); // We request an IP to connect to ("localhost") and // port number at that IP (2317). This establishes @@ -60,59 +64,69 @@ public class TcpSentryScenarioClient //////////////////////////////////////////////////////////////////////////////////////////// // Assignment code - String myName = new String(); + String myName; // input stream and output stream - InputStream inputStream = socket.getInputStream(); - Reader inputStreamReader = new InputStreamReader(inputStream); - BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + InputStream socketInputStream = socket.getInputStream(); + Reader socketInputStreamReader = new InputStreamReader(socketInputStream); + BufferedReader socketBufferedReader = new BufferedReader(socketInputStreamReader); - OutputStream outputStream = socket.getOutputStream(); - PrintStream printStream = new PrintStream(outputStream); - - String serverMessage = bufferedReader.readLine(); // blocks - System.out.println(prefix + ": message received from server='" + serverMessage + "'"); + OutputStream socketOutputStream = socket.getOutputStream(); + PrintStream socketPrintStream = new PrintStream(socketOutputStream); - String sentryResponse = bufferedReader.readLine(); - System.out.println ("Sentry: " + sentryResponse); - - if (sentryResponse.equals(HALT_WHO_GOES_THERE)) + while(true) // loop to handle query/response protocol { - // user provides name from console - myName = System.console().readLine(); - printStream.println(myName); // send it back to dispatch server -// System.out.println ("[trace] console return: " + myName); - - sentryResponse = bufferedReader.readLine(); - System.out.println ("Sentry: " + sentryResponse); + String sentryQuery = socketBufferedReader.readLine(); // this line blocks + System.out.println (sentryQuery); + + if (sentryQuery.endsWith(SENTRY_WATCH_PRESENT)) + { + // duly noted, do not respond to this and continue looping/processing + System.out.println (prefix + "(no response)"); + } + else if (sentryQuery.contains("Hello")) + { + System.out.println (prefix + "Hello officer."); + } + else if (sentryQuery.endsWith(HALT_WHO_GOES_THERE)) + { + System.out.println ("(visitors should type their name here)"); + // user provides name from console + myName = System.console().readLine(); // this line blocks, awaiting keyboard input from user + socketPrintStream.println(prefix + myName); // send it back to dispatch server + // System.out.println ("[trace] console return: " + myName); - if (sentryResponse.equals(YOU_MAY_PASS)) + if (myName.equalsIgnoreCase("quit") || myName.equalsIgnoreCase("exit")) + { + socketPrintStream.flush(); // ensure this final message goes through the socket + System.out.println (prefix + "Exiting the program."); + socket.close(); + System.exit(0); + } + } + else if (sentryQuery.endsWith(YOU_MAY_PASS)) { - System.out.println ("Thank you officer."); + System.out.println (prefix + "Thank you officer."); + break; } - else if (sentryResponse.equals(HOLD_IT_RIGHT_THERE)) + else if (sentryQuery.endsWith(HOLD_IT_RIGHT_THERE)) { - System.out.println ("OK I am outta here!"); + System.out.println (prefix + "OK I am outta here!"); + break; } // handling unexpected cases is important - else System.out.println ("I'm not sure what that means..."); + else System.out.println (prefix + "I'm not sure what that means, say again please..."); } - - System.out.println("======================================================="); + System.out.println("==============================================================================="); // To push this further, launch multiple copies of TcpSentryScenarioClient simultaneously - - if (myName.equalsIgnoreCase("quit") || myName.equalsIgnoreCase("exit")) - { - printStream.flush(); - socket.close(); - } } //////////////////////////////////////////////////////////////////////////////////////////// System.out.println(prefix + " complete"); // main method now exits - } catch (IOException e) { - System.out.println("*** Problem with " + prefix + "networking:"); // describe what is happening + } + catch (IOException e) { + System.out.println("*** " + prefix + "Problem with networking,"); // describe what is happening System.out.println(" " + e); // Provide more helpful information to user if exception occurs due to running twice at one time if (e instanceof java.net.BindException) @@ -124,5 +138,9 @@ public class TcpSentryScenarioClient System.out.println("*** Be sure to start the server before starting the client!"); } } + finally + { + System.out.println("pau, all done"); + } } } diff --git a/examples/src/TcpExamples/TcpSentryScenarioDispatchServer.java b/examples/src/TcpExamples/TcpSentryScenarioDispatchServer.java index fa03640ded..add710881e 100644 --- a/examples/src/TcpExamples/TcpSentryScenarioDispatchServer.java +++ b/examples/src/TcpExamples/TcpSentryScenarioDispatchServer.java @@ -24,7 +24,7 @@ import java.net.*; */ public class TcpSentryScenarioDispatchServer { - static String prefix = "[" + TcpSentryScenarioDispatchServer.class.getName() + "] "; + static String prefix = "[dispatcher] "; /** Default constructor */ public TcpSentryScenarioDispatchServer() @@ -39,44 +39,46 @@ public class TcpSentryScenarioDispatchServer { try { ServerSocket serverSocket = new ServerSocket(2317); - Socket clientConnectionSocket; - TcpSentryScenarioHandlerThread handlerThread; + Socket serverSocketConnection; + TcpSentryScenarioHandlerThread sentryHandlerThread; int connectionCount = 0; // state variable - System.out.println(prefix + "waiting and ready to accept socket connection from client..."); + System.out.println("==============================================================================="); + System.out.println(prefix + "startup, menu 1g.TcpSentryServer, " + TcpSentryScenarioDispatchServer.class.getName()); while (true) // infinite loop, handling client connections and dispatching another handler thread { - clientConnectionSocket = serverSocket.accept(); // block! until connected + System.out.println(prefix + "waiting and ready to accept socket connection from a new client..."); + serverSocketConnection = serverSocket.accept(); // block! until connected - connectionCount++; // unblocked, got another connection + connectionCount++; // now unblocked, we have gotten another connection // TODO option for the student, provide initial message *to the client* // that we are handing off to a dispatch thread... because that is polite behavior. // Plenty of code in Example3, we instead let our proxy thread // TcpSentryScenarioHandlerThread introduce itself to the client. - System.out.println("============================================================="); - System.out.println(prefix + ".handlerThread created for connection #" + connectionCount + "..."); + System.out.println(prefix + "received socket connection, creating handlerThread for visitor #" + connectionCount + "..."); // hand off this aready-created and connected socket to constructor - handlerThread = new TcpSentryScenarioHandlerThread(clientConnectionSocket); - handlerThread.start();// invokes the run() method in that object - System.out.println(prefix + ".handlerThread is now dispatched and running, using most recent connection..."); + sentryHandlerThread = new TcpSentryScenarioHandlerThread(serverSocketConnection); // creation logs a message + sentryHandlerThread.start();// invokes the run() method in that object, which sends initial reply on the socket + System.out.println(prefix + "a new sentry is now dispatched and running, using socket connection #" + connectionCount); + System.out.println("==============================================================================="); // while(true) continue looping, serverSocket is still waiting for another customer client } } catch (IOException e) { - System.out.println("Problem with " + prefix + " networking:"); // describe what is happening - System.out.println("Error: " + e); + System.out.println("*** " + prefix + "Problem with networking,"); // describe what is happening + System.out.println(" " + e); // Provide more helpful information to user if exception occurs due to running twice at one time - if (e instanceof java.net.BindException) { + if (e instanceof java.net.BindException) { System.out.println("*** Be sure to stop any other running instances of programs using this port!"); } System.exit(-1); } - System.out.println("============================================================="); // execution complete + System.out.println("==============================================================================="); // execution complete } } diff --git a/examples/src/TcpExamples/TcpSentryScenarioHandlerThread.java b/examples/src/TcpExamples/TcpSentryScenarioHandlerThread.java index 37fe6051db..ea41a18761 100644 --- a/examples/src/TcpExamples/TcpSentryScenarioHandlerThread.java +++ b/examples/src/TcpExamples/TcpSentryScenarioHandlerThread.java @@ -33,17 +33,18 @@ import java.util.List; */ public class TcpSentryScenarioHandlerThread extends Thread { - /** Sentry Scenario access list + /** Sentry Scenario access list, as written this list is case sensitive. * See {@linktourl https://stackoverflow.com/questions/1005073/initialization-of-an-arraylist-in-one-line } */ public static List<String> allowedNamesList = - Arrays.asList("Tim", "Stephen", "Mark", "Rene", "Simon", "James", "Ethan", "Jin Hong"); + Arrays.asList("Tim", "Stephen", "Mark", "Rene", "Simon", "James", "Ethan", "Jin Hong", "Don"); - public static final String HALT_WHO_GOES_THERE = "Halt who goes there?"; - public static final String YOU_MAY_PASS = "You may pass, have a great NPS MOVES day!"; - public static final String HOLD_IT_RIGHT_THERE = "You may not pass, leave immediately or else"; + public static final String SENTRY_WATCH_PRESENT = "Announcement: the sentry watch is present and standing guard."; + public static final String HALT_WHO_GOES_THERE = "Halt who goes there?"; + public static final String YOU_MAY_PASS = "You may pass, have a great MOVES day!"; + public static final String HOLD_IT_RIGHT_THERE = "You may not pass! Leave immediately or else..."; - private static final String prefix = "[" + TcpSentryScenarioHandlerThread.class.getName() + "] "; + private static final String prefix = "[sentry] "; /** The socket connection to a client */ Socket socket; @@ -57,6 +58,7 @@ public class TcpSentryScenarioHandlerThread extends Thread TcpSentryScenarioHandlerThread(Socket socket) { this.socket = socket; + System.out.println(prefix + "1h.TcpSentryClient, " + TcpSentryScenarioHandlerThread.class.getName()); } /** * Program invocation and execution starts here - but is illegal and unwanted, so warn the unsuspecting user! @@ -78,51 +80,77 @@ public class TcpSentryScenarioHandlerThread extends Thread { try { - System.out.println(prefix + "starting to handle a thread..."); + System.out.println(prefix + "startup, menu 1g.TcpSentryServer, " + TcpSentryScenarioHandlerThread.class.getName()); + // now starting to handle the thread - // input stream and output stream - InputStream inputStream = socket.getInputStream(); - Reader inputStreamReader = new InputStreamReader(inputStream); - BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + // setup input stream and output stream + InputStream socketInputStream = socket.getInputStream(); + Reader socketInputStreamReader = new InputStreamReader(socketInputStream); + BufferedReader socketBufferedReader = new BufferedReader(socketInputStreamReader); - OutputStream outputStream = socket.getOutputStream(); - PrintStream printStream = new PrintStream(outputStream); + OutputStream socketOutputStream = socket.getOutputStream(); + PrintStream socketPrintStream = new PrintStream(socketOutputStream); final long TIMEOUT = 100; // 2000 milliseconds = 2 seconds, 10000 milliseconds = 10 seconds // System.out.println(prefix + " pausing for TIMEOUT=" + TIMEOUT + "ms" + // " to emulate computation and avoid server-side overload"); Thread.sleep(TIMEOUT); - - // ps is the PrintStream is the Java way to use System.print() to pass data along the socket. - printStream.println(prefix + "This message was written by the server "); // TODO insert socket count here! - printStream.flush(); // make sure that it indeed escapes current process and reaches the client //////////////////////////////////////////////////////////////////////////////////////////// // Assignment code + + // since this thread is running, a socket connection has already been received from dispatch server. + // PrintStream is the Java way to use System.print() to pass string data along the socket. + socketPrintStream.println(prefix + SENTRY_WATCH_PRESENT); + System.out.println(prefix + SENTRY_WATCH_PRESENT); + // make sure that message indeed escapes current process and is pushed through socket to reach the client + socketPrintStream.flush(); - printStream.println(HALT_WHO_GOES_THERE); - System.out.println ("socket send: " + HALT_WHO_GOES_THERE); + // now the query-response interactions begin... + socketPrintStream.println(prefix + HALT_WHO_GOES_THERE); + System.out.println(prefix + HALT_WHO_GOES_THERE); - String clientResponse = bufferedReader.readLine(); - System.out.println ("clientResponse: " + clientResponse); + String clientResponse = socketBufferedReader.readLine(); + System.out.println (clientResponse); + // trim prefix if neccessary + int messageIndex = clientResponse.indexOf("]"); + if (messageIndex > 0) + clientResponse = clientResponse.substring(messageIndex + 1).trim(); - if (clientResponse.equalsIgnoreCase("quit") || clientResponse.equalsIgnoreCase("exit")) + if (clientResponse.trim().equalsIgnoreCase("quit") || + clientResponse.trim().equalsIgnoreCase("exit")) { - printStream.flush(); + System.out.println (prefix + "Exiting the program."); socket.close(); + System.exit(0); // shuts down thread, not dispatch server + } + // simple response + socketPrintStream.println(prefix + "Hello, " + clientResponse); + System.out.println(prefix + "Hello, " + clientResponse); + + // now check credential and respond accordingly + if (allowedNamesList.contains(clientResponse)) + { + socketPrintStream.println(prefix + YOU_MAY_PASS); + System.out.println(prefix + YOU_MAY_PASS); + } + else + { + socketPrintStream.println(prefix + HOLD_IT_RIGHT_THERE); + System.out.println(prefix + HOLD_IT_RIGHT_THERE); } - System.out.println ("Hello, " + clientResponse); //////////////////////////////////////////////////////////////////////////////////////////// -//// socket.close(); // all clear, no longer need socket - System.out.println(prefix + "finished handling a thread, now exit."); - System.out.println("============================================================="); // execution complete +// socket.close(); // all clear, no longer need socket + System.out.println(prefix + "this visitor interaction is complete."); + System.out.println("================================================================================="); + // execution complete } catch(IOException | InterruptedException e) // either a networking or a threading problem { - System.out.println("Problem with " + prefix + " networking:"); // describe what is happening - System.out.println("Error: " + e); + System.out.println("*** " + prefix + "Problem with networking,"); // describe what is happening + System.out.println(" " + e); // Provide more helpful information to user if exception occurs due to running twice at one time if (e instanceof java.net.BindException) -- GitLab