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.
}
}
}