Downloading RMI Stubs In the text we copied the stub, created by rmic, to the client. More flexibly, and powerfully, we can download the stub from the server. We need to run an HTTP server in the same directory as the RMI server. To simulate the process on one machine, we use two different directories for the client and server. We do not copy the stub to the client folder. We need to modify ThreadedWebServer to return a binary file rather than a text file. We show the modified HTTP server code below. We compile it in the server directory. In addition to the steps in the text we start the HTTP server using start java ThreadedWebServer 11111 When we start the RMI server, we need to specify a codebase, which is a URL from which the client can download the stub. When the client does a lookup, the RMI registry annotates its response with the codebase and the client downloads the stub automatically. The command to start the RMI server is start java -Djava.rmi.server.codebase=http://host:11111/ -Djava.security.policy=d:\policy.txt FortuneServer host where host is the address of the host computer. From the client directory, the command to run the client remains java -Djava.security.policy=d:\policy.txt FortuneClient host Revised ThreadedWebServer.java import java.net.*; import java.io.*; import java.util.StringTokenizer; public class ThreadedWebServer { public static void main(String [] args) { try { ServerSocket server = new ServerSocket(Integer.parseInt(args[0])); ThreadedWebServer web = new ThreadedWebServer(); while(true) { Socket client = server.accept(); web.new ClientThread(client); System.out.println("ThreadedWebServer Connected to " + client.getInetAddress()); } }catch(Exception e) { e.printStackTrace(); } } class ClientThread extends Thread { Socket client; BufferedReader fromClient; DataOutputStream toClient; public ClientThread(Socket c) { try { client = c; fromClient = new BufferedReader (new InputStreamReader(client.getInputStream())); toClient = new DataOutputStream(client.getOutputStream()); start(); }catch(Exception e) { e.printStackTrace(); } } public void run() { try { String s; s=fromClient.readLine(); StringTokenizer tokens = new StringTokenizer(s); if (!(tokens.nextToken()).equals("GET")) { toClient.writeBytes("HTTP/1.0 501 Not Implemented\r\n\r\n"); } else { String filename = tokens.nextToken(); filename = filename.substring(1); System.out.println(filename); File f = new File(filename); int length = (int)f.length(); byte[] bytes = new byte[length]; while (!(s = fromClient.readLine()).equals("")); toClient.writeBytes("HTTP/1.0 200 OK\r\n"); toClient.writeBytes("Content-type: text/plain\r\n\r\n"); BufferedInputStream file = new BufferedInputStream (new FileInputStream(f)); file.read(bytes); toClient.write(bytes); file.close(); } fromClient.close(); toClient.close(); client.close(); }catch(Exception e) { e.printStackTrace(); } } } }