package TcpExamples; import static TcpExamples.TcpSentryHandlerThread.APPROACH_THE_GATE; import static TcpExamples.TcpSentryHandlerThread.HALT_WHO_GOES_THERE; import static TcpExamples.TcpSentryHandlerThread.HOLD_IT_RIGHT_THERE; import static TcpExamples.TcpSentryHandlerThread.SENTRY_WATCH_PRESENT; import static TcpExamples.TcpSentryHandlerThread.YOU_MAY_PASS; import static TcpExamples.TcpSentryHandlerThread.PAY_ATTENTION; import java.io.*; import java.net.*; /** * This client program establishes a socket connection to the {@link TcpExamples.TcpSentryDispatchServer}, * then checks how long it takes to read the single line it expects as a server response. * No fancy footwork here, it is pretty simple and similar to {@link TcpExamples.TcpExample3Client}. * * @see TcpSentryDispatchServer * @see TcpSentryHandlerThread * @see TcpExample4Client * @see TcpExample4DispatchServer * @see TcpExample4HandlerThread * * @see <a href="../../../src/TcpExamples/TcpSentryTerminalLog.txt" target="blank">TcpSentryTerminalLog.txt</a> * @see <a href="../../../src/TcpExamples/TcpExample4SequenceDiagram.png" target="blank">TcpExample4SequenceDiagram.png</a> * @see <a href="../../../src/TcpExamples/TcpExample4SequenceSketch.png" target="blank">TcpExample4SequenceSketch.png</a> * * @author Don Brutzman * @author Don McGregor * @author MV3500 class */ public class TcpSentryClient { /** who is speaking, by role */ static String ACTOR = "[client] "; /** Default constructor */ public TcpSentryClient() { // no action needed here } static String DESTINATION_HOST = "localhost"; static int MAX_LOOP_COUNT = 6; /** * Program invocation, execution starts here * @param args command-line arguments */ public static void main(String[] args) { try { System.out.println("==============================================================================="); System.out.println(ACTOR + "startup, menu 1h.TcpSentryClient, " + TcpSentryClient.class.getName()); System.out.println(ACTOR + "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(ACTOR + "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 // a connection to that IP in the form of the Socket // object; the server uses a ServerSocket to wait for // connections. // open a socket for each loop Socket socket = new Socket(DESTINATION_HOST, 2317); //////////////////////////////////////////////////////////////////////////////////////////// // Assignment code String myName = new String(); // input stream and output stream InputStream socketInputStream = socket.getInputStream(); Reader socketInputStreamReader = new InputStreamReader(socketInputStream); BufferedReader socketBufferedReader = new BufferedReader(socketInputStreamReader); OutputStream socketOutputStream = socket.getOutputStream(); PrintStream socketPrintStream = new PrintStream(socketOutputStream); while(true) // loop to handle query/response protocol { 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 (ACTOR + "(no response, observing situation)"); } else if (sentryQuery.toLowerCase().contains("hello")) { if (!myName.isBlank()) System.out.println (ACTOR + "(" + myName + ") Hello officer."); else System.out.println (ACTOR + " Hello officer."); // anonymous } else if (sentryQuery.endsWith(APPROACH_THE_GATE)) { // duly noted, do not respond to this and drive forward System.out.println (ACTOR + "(no response, driving forward to gate)"); } 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(ACTOR + myName); // send it back to dispatch server // System.out.println ("[trace] console return: " + myName); if (myName.equalsIgnoreCase("quit") || myName.equalsIgnoreCase("exit")) { socketPrintStream.flush(); // ensure this final message goes through the socket System.out.println (ACTOR + "Exiting the program."); socket.close(); System.exit(0); } } else if (sentryQuery.endsWith(PAY_ATTENTION)) { // better listen better, the prior query wasn't handled together // no response expected or provided } else if (sentryQuery.endsWith(YOU_MAY_PASS)) { System.out.println (ACTOR + "Thank you officer."); break; } else if (sentryQuery.endsWith(HOLD_IT_RIGHT_THERE)) { System.out.println (ACTOR + "OK I am outta here!"); break; } // handling unexpected cases is important else System.out.println (ACTOR + "I'm not sure what that means, say again please..."); } // continue looping until termination event occurs System.out.println("==============================================================================="); // To push the sentry software further, launch multiple copies of this TcpSentryClient simultaneously } //////////////////////////////////////////////////////////////////////////////////////////// System.out.println(ACTOR + " complete"); // main method now exits } catch (IOException e) { System.out.println("*** " + ACTOR + "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) { System.out.println("*** Be sure to stop any other running instances of programs using this port!"); } else if (e instanceof java.net.ConnectException) { System.out.println("*** Be sure to start the server before starting the client!"); } } finally { System.out.println(TcpSentryClient.class.getName() + " all done."); } } }