package examples.example2_one_client_OO; import java.io.BufferedReader; import java.io.Closeable; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket; import javax.swing.JOptionPane; /** *
 * NetworkingExamples project: examples.example2_one_client_OO.
 * 
 * A simple example of networking (Sockets) in which:
 *   -- A single Server and Client exchange information, one after the other.
 *   
 * This is the Client code.
 * 
 * This is the same example as {@link examples.example1_one_client}
 * except structured in a more OO way.  In particular, this structure has 3 classes:
 *   -- Main: for starting the program.
 *   -- Server: for initiating and running the Server.
 *   -- Client: for initiating and running the Client.
 * 
 * See {@link examples.example1_one_client#MainForServer} for:
 *   -- Exactly what information the Server and Client exchange in this demo.
 *   -- The 7 Key Statements that are all-you-need-to-know to do networking in Java.
 * 
 * See {@link examples.example3_one_client_OO_library} for this same example
 * but using the simple networking library in package {@link simpleNetworking}.
 * 
* * @author David Mutchler, based on the Java Tutorials on networking. May, 2009. */ public class Client implements Runnable { private BufferedReader in; private PrintWriter out; private Socket socketToCommunicateWithServer; /** *
	 * Constructs readers and writers for talking to the Server, as follows:
	 * 
	 * 1. Constructs a Socket to the Server, using the given hostname and port.
	 *    Note: The Server must be accepting clients at this point,
	 *    else the construction of the Socket by this Client will fail.
	 *  
	 * 2. Use that Socket to:
	 *    a. Get an InputStream.  Then decorate the InputStream
	 *       into a BufferedReader (for more efficient communication).
	 *    b. Get an OutputStream.  Then decorate the OutputStream
	 *       into a PrintWriter (for convenient ways to write messages).
	 *       
	 * Finally, this constructor:
	 * 3. Starts a Thread in which the Client repeatedly communicates with the
	 *    Server (so that you can see a simple example of network communication).
	 * 
* * @param hostName HostName or IP address of the Server to which to connect. * @param port Port to use for the Socket that connects to the Server * at the given hostName. * @throws Throwable if any Exception or Error occurs. */ public Client(String hostName, int port) throws Throwable { try { //------------------------------------------------------------------------------------- // KEY #7: Connect to the given Server, getting a Socket for communicating with it. this.socketToCommunicateWithServer = new Socket(hostName, port); //------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------- // From the Socket, construct a BufferedReader for reading from the Client. this.in = new BufferedReader(new InputStreamReader( this.socketToCommunicateWithServer.getInputStream())); //------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------- // From the Socket, construct a PrintWriter for writing to the Client. this.out = new PrintWriter( this.socketToCommunicateWithServer.getOutputStream(), true); //------------------------------------------------------------------------------------- new Thread(this).start(); } catch (Throwable exception) { this.close(); throw exception; } } /** *
	 * A simple example of communication between this Client and the Server.
	 * 
	 * It behaves as follows:
	 * 
	 * Initiate the protocol by sending a random number to the Server. Then:
	 * 
	 * Repeatedly, until the Server sends STOP or the user says to stop:
	 *   -- Get a number from the Server.
	 *   -- Add a random number between 0 and 10 to it.
	 *   -- After pausing 0 to 5 seconds, send the revised number to the Server.
	 *   
	 * The Server can send whatever number it wishes at each iteration;
	 * in fact, the particular Server in this program takes the number
	 * that the Client sends it, asks the user for another number,
	 * and sends the sum of the two numbers back to this Client.
	 * 
	 * If the user says to stop, the Client sends a STOP message to the Server
	 * so that the Server will stop too.
	 * 
*/ @Override public void run() { try { //------------------------------------------------------------------------------------- // Now start communicating with the Server. //------------------------------------------------------------------------------------- int number; String dataFromServer; int dataFromUser; JOptionPane.showMessageDialog(null, "This Client is running on " + InetAddress.getLocalHost().getCanonicalHostName() + "\n" + "which is IP address " + InetAddress.getLocalHost().getHostAddress() + "\n\n"); number = (int) (Math.random() * 100); JOptionPane.showMessageDialog(null, "The Client starts the ball rolling with the random number " + number); //----------------------------------------------------------------------------- // Write to the Server. this.out.println(number); //----------------------------------------------------------------------------- while (true) { //----------------------------------------------------------------------------- // Read from the Server. dataFromServer = this.in.readLine(); //----------------------------------------------------------------------------- if (dataFromServer.equals("STOP")) { // Server says to stop. JOptionPane.showMessageDialog(null, "Client ended because the Server asked it to do so"); break; } number = (int) (Math.random() * 10); // What the Client does in this example. dataFromUser = JOptionPane.showConfirmDialog( null, "The Client got " + dataFromServer + " from the Server.\n\n" + "The Client chooses to add " + number + " to the above.\n\n" + "Thus the Client will send " + (number + Integer.parseInt(dataFromServer)) + " to the Server after a few seconds pause.\n\n" + "Press OK to continue or Cancel to quit this program.\n\n", "Continue?", JOptionPane.OK_CANCEL_OPTION); System.out.println(dataFromUser); if (dataFromUser == JOptionPane.CANCEL_OPTION) { // User selected Cancel in input dialog. JOptionPane.showMessageDialog(null, "Client ended because the user asked it to do so.\n\n" + "Tell the Server to stop too.\n\n"); this.out.println("STOP"); // Tell the Server to stop break; // and stop this Client. } Thread.sleep((long) (Math.random() * 5000)); //----------------------------------------------------------------------------- // Write to the Server. this.out.println(number + Integer.parseInt(dataFromServer)); //----------------------------------------------------------------------------- } } catch (IOException exception) { System.out.println(exception); JOptionPane.showMessageDialog(null, "Client ended, probably because the user closed the Server.\n\n"); } catch (Throwable exception) { System.out.println(exception); JOptionPane.showMessageDialog(null, "Client ended abnormally. See stack trace."); exception.printStackTrace(); } this.close(); } /** * Closes all resources that this Client uses: writer, reader, socket. */ void close() { Closeable[] resourcesToClose = {this.out, this.in}; JOptionPane.showMessageDialog(null, "Closing the client's resources."); for (Closeable resource : resourcesToClose) { try { resource.close(); } catch (Exception exception) { // Ignore; we made our best effort at closing the resource. } } try { this.socketToCommunicateWithServer.close(); } catch (Exception exception) { // Ignore; we made our best effort at closing the resource. } } }