package server; import client.ClientDataInterface; import java.rmi.*; import java.rmi.server.*; import javax.swing.*; import java.awt.*; /**** * * Class Server is a simple illustration of a remote server that uses RMI * communication. The server provides three typical methods to a client: * receiveClientInput, compute, and getServerOutput. * These methods are described further in their respective method * documentation. *
* The main method of the server accepts two command-line arguments. * The first argument is the name of the host computer on which the server * runs. The hostname may be suffixed with a colon-delimited port number. If * the port number is not present, the rmiregistry on the host is assumed to be * running on the well-known port 1099. So, e.g., a legal hostname could be * "waldorf.csc.calpoly.edu" or "waldorf.csc.calpoly.edu:1098", the latter * selecting alternate registry port 1098. *
* The second command-line argument is an optional flag indicating if the * server's GUI should be displayed when it runs. If the argument is missing, * the default behavior is to display the GUI. If the second argument is * "-nd", then no GUI display is shown. Using the "-nd" argument is * useful when the server is run in a context where there is no support for a * Java GUI display, for example, running the server on a UNIX machine like * waldorf when logged into waldorf via telnet from a Windows PC. *
* See the example Client class * for a description of how a client connects to this server and uses its * services. *
* It is noteworthy in this example that all method calls are initiated from
* the client. I.e., the computation is 100% client-driven. The server calls
*
* This client-driven computation could be replaced with a server-driven form,
* where the server calls client's methods. Or there could be some combined
* form, e.g., the client performs a push of its input data, and the server
* responds with a push its output. Whether to use a client- or sever-driven
* form of computation depends on a number of factors, including where the
* end-user fits into the computation, which side should perform input data
* validity checking, and what security concerns there are. Details of these
* issues are beyond the scope of this example.
*
*/
public class Server extends UnicastRemoteObject implements ServerInterface {
/**
* Construct this by calling the parent constructor.
*/
public Server() throws RemoteException {
super();
}
/*-*
* Public client methods.
*/
/**
* Receive some input from the client. Store a local copy for computation
* use. Also, display the data in the server's display window, or output
* the data to stdout if no display is available.
*/
public void receiveClientInput(ClientDataInterface clientData)
throws RemoteException {
this.clientData = clientData;
if (displayOn) {
textField.setText(Integer.toString(clientData.getValue()));
}
else {
System.out.println("Received Client Data: " +
Integer.toString(clientData.getValue()));
}
}
/**
* Perform some computation using the client input. In this case, we
* simply add 1 to the numeric input value received by the
* receiveClientInput method.
*/
public void compute() throws RemoteException {
serverOutput = clientData.getValue() + 1;
}
/**
* Return computation results back to the client, when the client calls for
* it.
*/
public Object getServerOutput() throws RemoteException {
return new Integer(serverOutput);
}
/*-*
* Protected setup methods.
*/
/**
* Set up the display as a JFrame with a labeled text field. The
* hostname input is the command-line argument from main.
*/
protected static void setupDisplay(String hostname) {
/*
* Allocate the frame and its innards.
*/
JFrame frame = new JFrame();
JPanel panel = new JPanel();
Box box = Box.createHorizontalBox();
/*
* Add the text field.
*/
textField = new JTextField(8);
box.add(new JLabel("Received Client Data: "));
box.add(textField);
/*
* Add border for some spacing.
*/
panel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
panel.add(box, BorderLayout.CENTER);
/*
* Add to, pack, and make visible the frame.
*/
frame.setTitle(hostname + " server");
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
/**
* Perform the necessary setup for remote execution. The hostname
* input is a server name with optional port number, e.g.,
* "waldorf.csc.calpoly.edu" or
* "waldorf.csc.calpoly.edu:1098". Server setup entails the
* following processing:
*