【问题标题】:RMI: does rmi server at the same time can work only with one network interfaceRMI: rmi server 是否只能同时使用一个网络接口
【发布时间】:2016-07-30 14:06:59
【问题描述】:

我有 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 服务器同时只能使用一个网络接口而无需任何操作系统设置?

【问题讨论】:

  • 我认为端口比网络接口更成问题
  • @cricket_007 我不明白你的意思——我对使用 rmi 的端口没有任何问题。问题在于使用不同的网络接口。
  • 那我可能理解错了。两个网络接口是否解析为相同的主机名和内容?
  • @cricket_007 是的。但是,我正在寻找不需要操作系统设置的解决方案。
  • '这是否意味着在一个 JVM 实例中,rmi 服务器同时只能使用一个网络接口?':不,它没有。

标签: java rmi


【解决方案1】:

设置java.rmi.server.hostname 只会影响写入存根的内容。对听力没有影响。 RMI 始终在 0.0.0.0 进行侦听,除非您使用不这样做的 RMIServerSocketFactory

【讨论】:

  • @JimJim2000 如果您还有更多此类问题,我建议您阅读我的书java.rmi:远程方法调用指南, Pitt & McNiff,Addison Wesley 2001。不再印刷,但周围有大量 s/h 副本。到目前为止,您提出的所有问题都包含在其中。
  • 谢谢你的建议,我去看看。你的答案呢。假设我们有一个 JVM 实例,上面有两个 RmiServer 192.168.1.0:2525 和 192.168.1.1:3636。然后仅适用于一台服务器的存根将起作用,因为据我所知,您在所有存根中的回答都将写成相同的java.rmi.server.hostname?
  • 一段时间过去了,我又回到了这个问题。是的,我写的是正确的。但它没有给出解决方案,只是解释了问题。我已经阅读了您在不同站点上的许多帖子,不幸的是,当有多个网络接口和一个实例 JVM 在不同的网络接口上创建不同的 RMI 服务器时,我找不到您提出的任何解决方案来解决这种情况。您能说一下您是否知道此类问题的解决方案?
  • @Pavel_K 什么问题?我在这里回答说它在 0.0.0.0 上侦听。这消除了任何数量的网络接口的任何问题。
【解决方案2】:

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

【讨论】:

  • 这完全没有必要。没有实际问题需要解决。没有您所说的“RMI 限制”。我没有错。
猜你喜欢
  • 1970-01-01
  • 2013-01-22
  • 1970-01-01
  • 2015-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-18
  • 1970-01-01
相关资源
最近更新 更多