RMI客户端无法查找服务器 - java.rmi.UnmarshalException

时间:2014-04-11 12:16:00

标签: java rmi policy

我在两台不同的机器上有一个java rmi服务器和一个java rmi客户端

服务器基本上是一个斐敌计算器。它接收一堆数字并根据它们计算Fibonacci序列。

客户端只需发送一堆数字供服务器计算。

FiboServer项目由三个类组成:

  • IFibonacci.java:界面
  • Fibonacci.java:实现先前定义的接口
  • FibonacciServer.java:拥有main,并运行服务器

FibonacciServer.java:

package fiboserver;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class FibonacciServer {
    public static void main(String args[]){

        if (System.getSecurityManager() == null) {
            System.setProperty("java.security.policy", "server.policy");
            System.setSecurityManager(new SecurityManager());
        }

        try{
            IFibonacci fib = new Fibonacci();

            // Bind the remote object's stub in the registry
            Registry registry = LocateRegistry.createRegistry(1099);
            registry.rebind("fibonacci", fib);

            System.out.println("Fibonacci Server ready.");
        }catch(RemoteException rex){
            System.err.println("Exception in Fibonacci.main " + rex);
        }
    }
}

客户端项目只有一个类:FibonacciClient.java。

FibonacciClient.java:

package fiboclient;

import fiboserver.IFibonacci;
import java.math.BigInteger;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class FibonacciClient {

    public static void main(String[] args) {

        if (System.getSecurityManager() == null) {
            System.setProperty("java.security.policy", "client.policy");
            System.setSecurityManager(new SecurityManager());
        }

        try{
            //args[0] = server Public IP
            Registry registry = LocateRegistry.getRegistry(args[0]);
            IFibonacci calculator = (IFibonacci) registry.lookup("fibonacci");

            //the rest of the args are just numbers to calculate
            for(int i = 1; i < args.length; i++){
                try{
                    BigInteger index = new BigInteger(args[i]);
                    BigInteger f = calculator.getFibonacci(index);

                    System.out.println("The " + args[i] + "th Fibonacci number "
                            + "is " + f);
                }catch(NumberFormatException e){
                    System.err.println(args[i] + " is not an integer.");
                }
            }
        }catch(RemoteException e){
            System.err.println("Remote object threw exception " + e);
        } catch (NotBoundException e) {
            System.err.println("Could not find the requested remote object on "
                    + "the server: " + e);
        }
    }

}

两个项目都有一个策略文件,服务器有server.policy,客户端有一个client.policy文件。两个文件都具有相同的内容:

grant{
    permission java.security.AllPermission;
};

我正在使用java -jar FiboServer.jar -Djava.net.preferIPv4Stack=true -Djava.rmi.server.hostname=12.34.56.789

在服务器计算机中启动FiboServer

我使用java -jar FiboClient.jar 12.34.56.789 1 2 3 4 5启动客户端。

服务器启动没有问题。但是当我启动客户端时,我收到错误:

Remote object threw exception java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
    java.lang.ClassNotFoundException: fiboserver.IFibonacci

StackOverflow上的搜索使我确信这与RMI注册表错误或策略文件错误有关。但是我知道正在正确读取策略文件,我认为它们没有任何错误。

我做错了什么?为什么这不起作用?


修改

IFibonacci.java:

package fiboserver;

import java.math.BigInteger;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface IFibonacci extends Remote{
    public BigInteger getFibonacci(int n) throws RemoteException;
    public BigInteger getFibonacci(BigInteger n) throws RemoteException;
}

JAR文件:

FibonacciClient.jar的内容:

|META-INF
|----Manifest.mf
|fiboclient
|----FibonacciClient.class

FibonacciServer.jar的内容:

|META-INF
|----manifest.mf
|fiboserver
|----IFibonacci.class
|----FibonacciServer.class
|----Fibonacci.class

1 个答案:

答案 0 :(得分:3)

客户端没有在其类路径中可用的异常中命名的类。您需要部署它,以及它所依赖的任何类,依此类推,直到关闭。

您可能已将远程接口重命名/复制到客户端的另一个程序包中。你不能这样做。它必须与服务器和客户端相同。相同的名称,相同的方法,相同的包。

NB客户端远程对象中的消息引发异常&#39;不正确。它可能是throw()抛出异常。不要因为假设可能不是这样的事情而迷惑自己。只需打印实际的错误消息,异常和堆栈跟踪。