< Zurück | Inhalt | Weiter >

5.8.4 Setting Up Servers and Clients

So far, we have written an RMI interface, a server implementation, and a client implementation. We have generated RMI stubs for our RMI object. We are


19. Be careful! If you have one or more Java SDKs installed and you have the GNU Compiler for Java installed, watch out for your PATH. The Java compiler and the Java runtime from the JDK don’t collide with gcj because the compiler has a different name and gcj compiles to native binaries. But gcj does have an rmic compiler, and it is usually in /usr/bin, which is usually ahead of your JDK in the executable path. If you run rmic and it explodes with errors, make sure you aren’t running the rmic from gcj against .class files from a JDK. (And, yes, this bit me and had me confused for a while!)

20. http://java.sun.com/j2se/1.4.2/docs/tooldocs/solaris/rmic.php

almost ready to fire our system up and give it a try. But first, we’ll give you some information about our sample environment and talk very briefly about security.21 What RMI Servers and Clients Need to Be Able to Do

RMI servers and clients need to be able to listen for connections on network ports, and they need to be able to initiate connections on network ports. Back in the Java 1.1 days, there were no limits on what RMI methods could do. The CLASSPATH was assumed to be trusted. With the RMI 1.2 protocol specifica- tion, the ability to actually pass bytecodes between VMs over RMI was added. That means that it is possible for clients to pass code to servers. Obviously, this opens a lot of possible security risks. For this reason, RMI got a security man- agement layer. It is the same security manager as the one that applets use. It also provides a default security manager class that has virtually all such capabil- ities safely turned off. We need to turn on some of these capabilities in order to make our sample work.

The RMI system expects Java classes to be made available through one of two paths.

1. The CLASSPATH, either the environment variable or on the command line.

2. Through a property that points at URL. This URL may be a file: URL, or an http: URL.

We are going to do the simplest case for now. We will have our compiled code installed on both our server system and our client system. The classes will all be referenced relative to the default classpath (in other words, relative to “.”, the current directory).

This is not the typical case. The most common case will be for the classes to be available in a JAR file via a Web server, and for the java.rmi.server.codebase property to be set to point to the JAR file via an http: URL.


21. We’re going to gloss over this subject for now.


Example 5.13 A Java security policy file suitable for the RMI example

grant {

permission java.net.SocketPermission "*:1024-65535", "connect,accept"; permission java.net.SocketPermission "*:80", "connect,accept";


image Our Environment

We have two machines. One, penfold, is our server machine. The other, grovel, is our client machine. To keep things straight in our samples, the shell prompts will have the host names in them.

If you are using a JDK that supports the 1.2 RMI specification (and we hope you are—it’s in all current JDKs), you have to give your server and your client permission to access the network ports needed to run. By default, the Java runtime will look for a security policy file in the home directory of the user running the VM. The default name of the file is .java.policy. Exam- ple 5.13 shows what we suggest you put in this file, at least to run this example.


You will have to put this in your home directory both on the server and on all client machines.

image Compiling and Running the Server

Our packages here follow Sun’s suggested naming convention of your domain name, reversed, followed by your package names. It so happens that Mr. Schwarz’s domain is called multitool.net (named after his first book, Multitool Linux), so we put all of these classes in a package called net.multitool.RMIDemo.

For all of the examples in this section, as well as the following section on building and running the client, assume that our current working directory is the directory that contains the net directory of our source code.

The output you see in Example 5.14 includes the result of running our client once. Note that the SessionImpl class doesn’t terminate. It keeps running to service clients indefinitely.


Example 5.14 Compiling and running our server on penfold.

penfold$ javac net/multitool/RMIDemo/SessionImpl.java penfold$ rmic net.multitool.RMIDemo.SessionImpl penfold$ rmiregistry &


penfold$ java net.multitool.RMIDemo.SessionImpl Asked to add 47 and 13

image Compiling and Running the Client

Example 5.15 shows the actual steps we ran to build and run the client.


Example 5.15 Compiling and running our client on grovel

grovel$ javac net/multitool/RMIDemo/Client.java grovel$ javac net/multitool/RMIDemo/SessionImpl.java

grovel$ /usr/java/jdk/bin/rmic net.multitool.RMIDemo.SessionImpl grovel$ java net.multitool.RMIDemo.Client

Pointless RMI Client. 47+13=60, right? grovel$



We compile the server class, SessionImpl, on the client side and run rmic against it just to produce the stubs the client requires. You could copy the stub classes from the server machine, or you could put them in a JAR file, put that file on a Web server, and have the java.rmi.server.codebase property point to that JAR file. We’re taking the simple way here, but in a real implementation, you would not do it this way. We’ll cover more realistic cases later.