package examples.example1_one_client; import java.io.BufferedReader; import java.io.Closeable; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.BindException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import javax.swing.JOptionPane; /** *
* NetworkingExamples project: examples.example1_one_client. * * A simple example of networking (Sockets) in which: * -- A single Server and Client exchange information, one after the other. * * This is the Server's code. * * Brevity is king in this example, so it has few comments / instructions after this * and is NOT organized in a OO way that permits easy reuse of code. * * See the other examples for an OO approach: * -- {@link examples.example2_one_client_OO} does this same example in a more OO way * -- {@link examples.example3_one_client_OO_library} does this same example * using the simple networking library in package {@link simpleNetworking} * -- {@link examples.example4_two_clients_OO_library} also uses the OO networking library {@link simpleNetworking} * -- {@link examples.example5_chat_OO_library} also uses the OO networking library {@link simpleNetworking} * * Run this example by: * * 1. On one computer, run MainForServer. * * It starts up, nothing else happens. * * 2. On another computer (or the same computer, your choice), run MainForClient. * * It asks in the console window/tab for the hostname of the Server. * Enter the name of the computer running MainForServer. * You can enter localhost if you are using a single computer for both processes. * * You should see (in successive dialog boxes): * -- Server got 42 from the Client and will add 1 to it and thus send 43 to the Client * -- Client got 43 from the Server and will add 10 to it and thus send 53 to the Server * -- Server got 53 from the Client and will add 1 to it and thus send 54 to the Client * -- Client got 54 from the Server and will add 10 to it and thus send 64 to the Server * etc * * Stop the programs by using the dialog boxes (which ask if you want to continue). * Stopping the programs in other ways may prevent them from releasing their resources * (and especially the PORT being used). Also, if the Client stops (for whatever reason) * without having connected to the Server, the Server is probably still running (without you * noticing it). In this situation, simply run the Client WITHOUT first starting the Server * to clear out the lock / running Server. * * Before running this program, you may need to tell your Firewall not to * block the port that this program uses (4444, chosen arbitrarily). * In Windows, do so by: * Control Panel ~ Windows Firewall ~ Exceptions tab ~ Add Port * and enter the port number (4444) with any name you like. * * Here is what the Server and Client are doing (to illustrate server/client communication): * -- The Server starts with the number 42 and repeatedly: * -- Adds 1 to its current number. * -- Sends that number to the Client. * -- Gets back a number from the Client * and makes that number the Server's current number. * * -- The Client repeatedly: * -- Gets a number from the Server. * -- Adds 10 to that number. * -- Sends that number back to the Server after pausing a few seconds. * * The Server's user can ask it to stop and the Client's user can ask it to stop. * In either case, the Server/Client sends a STOP message to the Client/Server to ask it to stop too. * * Note that most of the code is for handling errors. There are only 7 Key Statements * (see details in the code) that are all-you-need-to-know to do networking in Java: * * -- Key #1: Server constructs a ServerSocket. * * -- Key #2: Server uses its ServerSocket to accept a connection to a Client. * Note that accept blocks (waits) until a Client asks for a Connection. * See Key #7 for how the Client does so. * * -- Key #3: Constructs a BufferedReader that the Server can use to read * from the Client. The BufferedReader is constructed from the * Socket that the Server got from Key #2 statement. * * -- Key #4: Constructs a PrintWriter that the Server can use to write * to the Client. The PrintWriter is constructed from the * Socket that the Server got from Key #2 statement. * * -- Key #5: Server reads from the Client by using its BufferedReader. * * -- Key #6: Server writes to the Client by using its PrintWriter. * * For the last Key statement, turn to the Client: * * -- Key #7: Client constructs a Socket for communicating with the Server. * * The Client runs its Key #7 statement while the Server is waiting for * its Key #2 statement to complete; the Client's Key #7 statement causes * the Server's Key #2 statement to complete. * * The Client continues from its Key #7 Statement to do as the Server did: * -- Construct a BufferedReader and PrintReader (as per Key #3 and Key #4). * -- Use the BufferedReader and PrintReader to read from and write to the Server * (as per Key #5 and Key #6). * * Reading blocks (waits) for input to arrive; however, there are methods * available to see if any input has arrived yet. ** * @author David Mutchler, based on the Java Tutorials on networking. May, 2009. */ public class MainForServer { /** * Port: Both Server and Client must use the same one, and it must be open. */ static int PORT = 5444; private static Socket socketToCommunicateWithClient; private static BufferedReader in; private static PrintWriter out; /** * Constructs a Server and starts it running. * * @param commandLineArguments Ignored here. */ public static void main(String[] commandLineArguments) { try { //------------------------------------------------------------------------------------- // KEY #1: Construct a ServerSocket that accepts connections from Clients. ServerSocket serverSocket = new ServerSocket(MainForServer.PORT); //------------------------------------------------------------------------------------- JOptionPane.showMessageDialog(null, "The Server has started and will wait for a connection.\n\n" + "Start the Client AFTER pressing OK in this dialog.\n\n"); //------------------------------------------------------------------------------------- // KEY #2: Block (wait) until a Client connects; // get a Socket for communicating with that Client. MainForServer.socketToCommunicateWithClient = serverSocket.accept(); //------------------------------------------------------------------------------------- // Done with the ServerSocket, since we wanted to accept only a single Client in this example. serverSocket.close(); //------------------------------------------------------------------------------------- // KEY #3: From the Socket, construct a BufferedReader for reading from the Client. MainForServer.in = new BufferedReader(new InputStreamReader( MainForServer.socketToCommunicateWithClient.getInputStream())); //------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------- // KEY #4: From the Socket, construct a PrintWriter for writing to the Client. MainForServer.out = new PrintWriter( MainForServer.socketToCommunicateWithClient.getOutputStream(), true); //------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------- // Now start communicating with the Client. //------------------------------------------------------------------------------------- String dataFromClient, dataFromUser; int numberFromUser; JOptionPane.showMessageDialog(null, "This Server is running on " + InetAddress.getLocalHost().getCanonicalHostName() + "\n" + "which is IP address " + InetAddress.getLocalHost().getHostAddress() + "\n\n"); while (true) { //----------------------------------------------------------------------------- // KEY #5: Read from the Client. dataFromClient = MainForServer.in.readLine(); //----------------------------------------------------------------------------- if (dataFromClient.equals("STOP")) { // Client says to stop. JOptionPane.showMessageDialog(null, "Server ended because the Client asked it to do so.\n\n"); break; } dataFromUser = JOptionPane.showInputDialog( "The number from the Client is " + dataFromClient + ".\n\n" + "What do you want to add to it?\n\n" + "(Or press Cancel to quit this program.)\n\n"); if (dataFromUser == null) { // User selected Cancel in input dialog. JOptionPane.showMessageDialog(null, "Server ended because the user asked it to do so.\n\n" + "Tell the Client to stop too.\n\n"); MainForServer.out.println("STOP"); // Tell the Client to stop break; // and stop this Server. } try { numberFromUser = Integer.parseInt(dataFromUser); } catch (NumberFormatException exception) { JOptionPane.showMessageDialog(null, "You entered " + dataFromUser + "\n" + "which is not a number! I will use 0 instead.\n\n"); numberFromUser = 0; } //----------------------------------------------------------------------------- // KEY #6: Write to the Client. MainForServer.out.println(Integer.parseInt(dataFromClient) + numberFromUser); //----------------------------------------------------------------------------- } } catch (BindException exception) { System.out.println(exception); JOptionPane.showMessageDialog(null, "Server could not connect to port " + MainForServer.PORT + "\n" + "perhaps because that port is in use.\n\n"); } catch (SocketException exception) { System.out.println(exception); JOptionPane.showMessageDialog(null, "Server ended, either because it could not start" + " or (more likely) because the user closed the Client.\n\n"); } catch (IOException exception) { System.out.println(exception); JOptionPane.showMessageDialog(null, "Server ended, probably because the user closed the Client.\n\n"); } catch (Throwable exception) { System.out.println(exception); JOptionPane.showMessageDialog(null, "Server ended abnormally. See stack trace.\n\n"); JOptionPane.showMessageDialog(null, exception.getStackTrace()); } MainForServer.close(); } /** * Closes all resources that this Server uses: writer, reader, socket. */ private static void close() { Closeable[] resourcesToClose = {MainForServer.out, MainForServer.in}; JOptionPane.showMessageDialog(null, "Closing the Server's resources."); for (Closeable resource : resourcesToClose) { try { resource.close(); } catch (Exception exception) { // Ignore; we made our best effort at closing the resource. } } try { MainForServer.socketToCommunicateWithClient.close(); } catch (Exception exception) { // Ignore; we made our best effort at closing the resource. } } }