0
votes

I have to write a simple Java RMI Client/Server program that runs on two different machines. I was using Oracle's guide to help me:

I believe I have the server up and running, but I can't get the client to work. The first problem is how can the client java file compile if it creates a server object, but doesn't have the server code. I understand the server is supposed to export an object, but how can the client receive the object if it can't compile?

The guide says to do this:

The source files for this example can be compiled as follows:
javac -d destDir Hello.java Server.java Client.java
where destDir is the destination directory to put the class files in.

Yet, it seems like this assumes all of the code is in the same directory on one machine.

One solution I tried was to just copy the required class file onto the client machine, which allowed it to compile, but this seems impractical in the real world.

After it compiled, I tried to run the client and got this error:

Client exception: protocol = socket host = null
java.lang.IllegalArgumentException: protocol = socket host = null
asun.net.spi.DefaultProxySelector.select(DefaultProxySelector.java:170)

at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:384)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.(Socket.java:425)
at java.net.Socket.(Socket.java:208)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)

at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:147)

at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)

at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:341)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at Client.main(Client.java:14)

Here is my code:

Server

import java.rmi.server.UnicastRemoteObject;
import java.rmi.Remote;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.util.Scanner;

interface ServerInfo extends Remote {
   public String getDate() throws RemoteException;
   public String getUpTime() throws RemoteException;
   public String getMemUse() throws RemoteException;
   public String getNetstat() throws RemoteException;
   public String getUsers() throws RemoteException;
   public String getProcesses() throws RemoteException;
   public String Disconnect() throws RemoteException;
}

public class Server implements ServerInfo {
   public Server() {}

   public String getDate() throws RemoteException {
      System.out.println("Sent date");
      return TerminalCMD("date");
   }

   public String getUpTime() throws RemoteException {
      System.out.println("Sent uptime");
      return TerminalCMD("uptime");
   }

   public String getMemUse() throws RemoteException {
      System.out.println("Sent Memory Usage");
      return TerminalCMD("free -m");
   }

   public String getNetstat() throws RemoteException {
      System.out.println("Sent Netstat");
      return TerminalCMD("netstat");
   }

   public String getUsers() throws RemoteException {
      System.out.println("Sent Users");
      return TerminalCMD("who");
   }

   public String getProcesses() throws RemoteException {
      System.out.println("Sent Processes");
      return TerminalCMD("ps aux");
   }

   public String Disconnect() throws RemoteException {
      System.out.println("Disconnecting Client...");
      return "Disconnecting...";
   }

   public String TerminalCMD(String cmd) {
      String info = "";

      try {
         Process runTerminal = Runtime.getRuntime().exec(cmd);
         Scanner terminalReader = new Scanner(runTerminal.getInputStream());

         while(terminalReader.hasNextLine()) {
            info += terminalReader.nextLine() + "\n";
         }
      }
      catch(Exception e) {
         info = "Error";
      }

      return info;
   }

   public static void main(String[] args) {
      try {
         Server serverInstance = new Server();
     ServerInfo stub = (ServerInfo)UnicastRemoteObject.exportObject(serverInstance, 0);

     Registry registry = LocateRegistry.getRegistry(2541);
     registry.bind("Instance1", stub);
     System.out.println("Awaiting Connection...");
      }
      catch(Exception e) {
         System.out.println("Server error: " + e.getMessage()); 
         e.printStackTrace(); 
      }
   }
}

Client

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Scanner;

public class Client {
   public static void main(String[] args) {
      Scanner kbreader = new Scanner(System.in);
      int choice;
      boolean quit = false;
      String serverURL = "//CNT4505B.ccec.unf.edu/";

      try {
         Registry registry = LocateRegistry.getRegistry(serverURL, 2541);
     ServerInfo serverInstance = (ServerInfo)registry.lookup("Instance1");

         while(!quit) {
            System.out.println("1 - Host current Date and Time\n2 - Host uptime\n3 - Host memory use\n4 - Host Netstat\n5 - Host current users\n6 - Host running processes\n7 - Quit");
            choice = kbreader.nextInt();

            switch(choice) {
               case 1: System.out.println(serverInstance.getDate());
                  break;
               case 2: System.out.println(serverInstance.getUpTime());
                  break;
               case 3: System.out.println(serverInstance.getMemUse());
                  break;
               case 4: System.out.println(serverInstance.getNetstat());
                  break;
               case 5: System.out.println(serverInstance.getUsers());
                  break;
               case 6: System.out.println(serverInstance.getProcesses());
                  break;
               case 7: System.out.println(serverInstance.Disconnect());
                  quit = true;
                  break;
               default: System.out.println("Invalid selection.");
                  break;
            }
         }
      }
      catch(Exception e) {
         System.out.println("Client exception: " + e.getMessage()); 
         e.printStackTrace(); 
      }
   }
}
1

1 Answers

0
votes
  • The first argument to LocateRegistry.getRegistry() is a hostname, not a URL.

  • There are some components of any RMI system that are common to the server and the client. These include the remote interface class itself, and any application classes used within it, and so on until closure. Typically you create a third project for the shared classes.