Java RMI编译和运行时问题

时间:2015-12-04 02:42:23

标签: java server client rmi

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

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

指南说这样做:

  

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

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

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

编译完成后,我尝试运行客户端并收到此错误:

  

客户端异常:protocol = socket host = null
  java.lang.IllegalArgumentException:protocol = socket host = null
          asun.net.spi.DefaultProxySelector.select(DefaultProxySelector.java:170)

     

在java.net.SocksSocketImpl.connect(SocksSocketImpl.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)

     

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

     

at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
          在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)
          在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(); 
      }
   }
}

1 个答案:

答案 0 :(得分:0)

  • LocateRegistry.getRegistry()的第一个参数是主机名,而不是网址。

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