我有一台服务器和几个客户端。服务器应该能够将任务委派给客户端,因此我尝试实现RMI。我遵循了this教程,如果我将String用作参数和/或返回值,那么一切工作正常。

现在服务器应该将未定义的任务发送给客户端,因此我尝试使用Callable作为参数,但是程序因NotSerializableException崩溃。由于Callable没有实现Serializeable接口,所以我期望的结果是这样。

现在,我发现了一些使用Callable和Runnable作为参数的资源,这使我感到困惑。有什么技巧可以使其正常工作吗?还是我错过了重要的事情?也许有一种更合适的技术?

Resource1 S.33

Resource2 s。 5

这是我的代码:

// Client
public static void main(String[] args) throws InterruptedException {
    App app = new App();
    app.startClient();
    Thread.sleep(20000);//just for test purpose
}
private void startClient() {
    try {
        // create on port 1099
        Registry registry = LocateRegistry.createRegistry(1099);
        // create a new service named myMessage
        registry.rebind("calcClient", new CalculateRemoteImpl<String>());
    } catch (RemoteException e) {
        e.printStackTrace();
    }
    System.out.println("System is ready");
}
// RemoteInterface
public interface CalculateRemote<T> extends Remote {
    public T hello(Callable<T> hello) throws RemoteException;
}
// RemoteInterfaceImpl
public class CalculateRemoteImpl<T> extends UnicastRemoteObject implements CalculateRemote<T> {
    public T hello(Callable<T> hello) throws RemoteException {
        return (T) ("Hello " + hello);// just print address of object
    }
}




// Server
public static void main(String[] args) {
    App app = new App();
    app.doTest();
}
private void doTest() {
    try {
        // fire to localhost port 1099
        Registry myRegistry = LocateRegistry.getRegistry("127.0.0.1", 1099);
        // search for myMessage service
        CalculateRemote<String> impl = (CalculateRemote<String>) myRegistry.lookup("calcClient");
        // call server's method
        System.out.println("Message: " + impl.hello(new Callable<String>() {
            public String call() throws RemoteException, Exception {
                return "hello";
            }
        }));
        System.out.println("Message Sent");
    } catch (NotBoundException e) {
        e.printStackTrace();
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}
// And the same RemoteInterface
public interface CalculateRemote<T> extends Remote {
    public T hello(Callable<T> hello) throws RemoteException;
}




// stacktrace
java.rmi.MarshalException: error marshalling arguments; nested exception is:
    java.io.NotSerializableException: de.fhb.rmicalcserver.App$1
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:156)
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
    at $Proxy0.hello(Unknown Source)
    at de.fhb.rmicalcserver.App.doTest(App.java:30)
    at de.fhb.rmicalcserver.App.main(App.java:18)
Caused by: java.io.NotSerializableException: de.fhb.rmicalcserver.App$1
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1180)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
    at sun.rmi.server.UnicastRef.marshalValue(UnicastRef.java:292)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:151)

最佳答案

如果要将对象发送给未在客户端上部署类的客户端,则需要仔细研究RMI代码库功能。

关于java - 带有Callable的Java RMI,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22056910/

10-12 20:30