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

RMI: does rmi server at the same time can work only with one network interface

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

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

这是否意味着在一个 JVM 实例中,rmi 服务器同时只能使用一个网络接口,而无需任何 OS 设置?

设置java.rmi.server.hostname只影响写入存根的内容。对听力没有影响。 RMI 总是在 0.0.0.0 监听,除非你使用一个 RMIServerSocketFactory 而不是。

阅读 https://community.oracle.com/blogs/emcmanus/2006/12/22/multihomed-computers-and-rmi and this https://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);
        }
    }
}