RMI:rmi服务器同时只能使用一个网络接口

时间:2016-07-30 14:06:59

标签: java rmi

我有rmi服务器,我的计算机上有几个网络适配器。

为了不获取java.rmi.ConnectException: Connection refused to host: 127.0.1.1;我需要在我的rmi服务器上设置java.rmi.server.hostname属性(参见https://stackoverflow.com/a/15696021/5057736

这是否意味着在一个JVM实例中,rmi服务器同时只能在没有任何操作系统设置的情况下使用一个网络接口?

2 个答案:

答案 0 :(得分:1)

设置java.rmi.server.hostname只会影响写入存根的内容。它对听力没有影响。除非你使用的RMIServerSocketFactory没有使用,否则RMI始终会以0.0.0.0监听。

答案 1 :(得分:0)

在阅读https://community.oracle.com/blogs/emcmanus/2006/12/22/multihomed-computers-and-rmihttps://community.oracle.com/thread/1178328?start=0之后,我做了以下解决方案 - 在所有应用程序导出RMIRemoteObjects时,我们放在一个地方。此解决方案允许RMI在一个JVM实例中同时使用不同的网络接口。为每个套接字地址(网络接口+端口)创建RmiRemoteManager。在导出之前,我们需要定义java.rmi.server.hostname。此解决方案有效。请记住,这是RMI限制的解决方法。

class ClientSocketFactory implements RMIClientSocketFactory,Serializable{

    private InetAddress address;

    public ClientSocketFactory(InetAddress address)
    {
        this.address = address;
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException {
        Socket socket =new Socket(address, port);
        return socket;
    }

    @Override
    public boolean equals(Object that)
    {
        return that != null && this.getClass() == that.getClass();
    }
}

class ServerSocketFactory implements RMIServerSocketFactory{

    private InetAddress address;

    public ServerSocketFactory(InetAddress address)
    {
        this.address = address;
    }

    @Override
    public ServerSocket createServerSocket(int port) throws IOException{  
        return new ServerSocket(port, 0, address);
    }

    @Override
    public boolean equals(Object that)
    {
        return that != null && this.getClass() == that.getClass();
    }
}

public class RmiRemoteManager {

    private Registry registry;

    private InetSocketAddress socketAddress;

    private ServerSocketFactory serverSocketFactory;

    private ClientSocketFactory clientSocketFactory;

    public RmiRemoteManager(InetSocketAddress socketAddress) {
        try {
            this.socketAddress = socketAddress;
            serverSocketFactory=new ServerSocketFactory(InetAddress.getByName(socketAddress.getHostName()));
            clientSocketFactory=new ClientSocketFactory(InetAddress.getByName(socketAddress.getHostName()));
            //the registry is exported via createRegistry.
            registry = LocateRegistry.createRegistry(this.socketAddress.getPort(),clientSocketFactory,serverSocketFactory);
        } catch (UnknownHostException ex) {
            Logger.getLogger(RmiRemoteManager.class.getName()).log(Level.SEVERE, null, ex);
        } catch (RemoteException ex) {
            Logger.getLogger(RmiRemoteManager.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    private synchronized static Remote export(Remote remoteObject,InetSocketAddress sa,ClientSocketFactory csf,ServerSocketFactory ssf){
        try {
            System.setProperty("java.rmi.server.hostname",sa.getHostName());
            return UnicastRemoteObject.exportObject(remoteObject,sa.getPort(),csf,ssf);
        } catch (RemoteException ex) {
            Logger.getLogger(RmiRemoteManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public void export(Remote remoteObject,String url){
        try {
            Remote stub=export(remoteObject,socketAddress,clientSocketFactory,serverSocketFactory);
            remoteObjects.add(remoteObject);
            if (url!=null){
                urlsByRemoteObjects.put(remoteObject, url);
                registry.rebind(url, stub);
            }
        } catch (RemoteException ex) {
            Logger.getLogger(RmiRemoteManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}