Java RMI编译和运行时问题

Java RMI编译和运行时问题,java,server,client,rmi,Java,Server,Client,Rmi,我必须编写一个简单的JavaRMI客户机/服务器程序,在两台不同的机器上运行。我正在使用Oracle指南来帮助我: 我相信我已经启动并运行了服务器,但是我无法让客户端工作。第一个问题是,如果客户端java文件创建了一个服务器对象,但没有服务器代码,它如何编译。我知道服务器应该导出一个对象,但是如果不能编译,客户端如何接收对象呢 指南上说要做到这一点: 此示例的源文件可以按如下方式编译: javac-d destDir Hello.java Server.java Client.java 其

我必须编写一个简单的JavaRMI客户机/服务器程序,在两台不同的机器上运行。我正在使用Oracle指南来帮助我:

我相信我已经启动并运行了服务器,但是我无法让客户端工作。第一个问题是,如果客户端java文件创建了一个服务器对象,但没有服务器代码,它如何编译。我知道服务器应该导出一个对象,但是如果不能编译,客户端如何接收对象呢

指南上说要做到这一点:

此示例的源文件可以按如下方式编译:
javac-d destDir Hello.java Server.java Client.java
其中destDir是将类文件放入的目标目录

然而,这似乎是假设所有代码都在一台机器上的同一目录中

我尝试的一个解决方案是将所需的类文件复制到客户机上,这样就可以进行编译,但这在现实世界中似乎不切实际

编译后,我尝试运行客户端,但出现以下错误:

客户端异常:协议=套接字主机=空
java.lang.IllegalArgumentException:protocol=socket host=null
asun.net.spi.DefaultProxySelector.select(DefaultProxySelector.java:170)

位于java.net.socksocketimpl.connect(socksocketimpl.java:384)
在java.net.Socket.connect(Socket.java:579)
在java.net.Socket.connect(Socket.java:528)
位于java.net.Socket.(Socket.java:425)
位于java.net.Socket.(Socket.java:208)
位于sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)

位于sun.rmi.transport.proxy.rmismastersocketfactory.createSocket(rmismastersocketfactory.java:147)

位于sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
位于sun.rmi.transport.tcp.tcpcchannel.createConnection(tcpcchannel.java:216)

位于sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
位于sun.rmi.server.UnicastRef.newCall(UnicastRef.java:341)
在sun.rmi.registry.RegistryImpl_Stub.lookup(未知源)
位于Client.main(Client.java:14)

这是我的密码:

服务器

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(); 
      }
   }
}
客户

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(); 
      }
   }
}
  • LocateRegistry.getRegistry()
    的第一个参数是主机名,而不是URL

  • 任何RMI系统都有一些对服务器和客户机通用的组件。这些包括远程接口类本身,以及其中使用的任何应用程序类,等等,直到关闭为止。通常为共享类创建第三个项目