Java RMI地址解析问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java RMI地址解析问题相关的知识,希望对你有一定的参考价值。

我正在尝试重新编写一些基本的设计模式。我只有代码片段,没有完整的运行代码示例。一种叫做代理模式。

我只想通过远程调用方法。这是我的简单代码:

WebService.Java

public class WebService extends UnicastRemoteObject implements IRemote {

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {

        try {
            IRemote service = new WebService();
            Naming.rebind("RemoteCalculator", service);
        } catch (Exception e) {
            e.printStackTrace();
        }       
    }

    /** No arg default constructor */
    public WebService() throws RemoteException {    }

    /** Methods of remote interface */
    @Override
    public double getRoot(double v) throws RemoteException {        
        return Math.sqrt(v);
    }


}

...其中IRemote是一个简单的接口,用于扩展远程接口并定义单个示例方法(getRoot(double))的签名。

现在连接到远程的类:

test proxy.Java

public class TestProxy implements Remote{

    /**
     * @param args
     */
    public static void main(String[] args) {        
        new TestProxy().go(args[0]);
    }

    public TestProxy() {}

    public void go(String ip) {
        try {

            System.out.println("Trying to lookup for service ...");

            IRemote service = (IRemote) Naming.lookup("//" + ip + "/RemoteCalculator");

            System.out.println("done");

            double d = service.getRoot(5.0);

            System.out.println(d);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

我正在运行rmiregistry.exe并通过rmic.exe创建我的WebService_Stub.class,如某些文档中所示。本地连接127.0.0.1作为(ip-)参数工作正常。但即使端口(1099)已打开并通过telnet检查,也无法通过互联网进行连接。

当我从命令行开始时:

java net.mypackage.remote.TestProxy 78.2.2.2

它总是给出结果:

试图查找服务...已完成java.rmi.ConnectException:连接拒绝主机:192.168.1.51;嵌套的例外是:java.net.ConnectException:在sun.rmi的sun.rmi.transport.tcp.TCPChannel.createConnection(未知来源)sun.rmi.transport.tcp.TCPEndpoint.newSocket(未知来源)的连接超时.transport.tcp.TCPChannel.newConnection(未知源)位于java.rmi.server.RemoteObjectInvocationHandler的java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unkn own Source)中的sun.rmi.server.UnicastRef.invoke(未知源)。在net.gerdsmeier.remote.TestProxy.main(TestProxy.java:22)net.gerdsmeier.remote.TestProxy.go(TestProxy.java:39)上的$ Proxy1.getRoot(未知来源)调用(未知来源)引起:java.net.ConnectException:在java.net上的java.net.AbstractPlainSocketImpl.connectToAddress(未知来源)java.net.AbstractPlainSocketImpl.doConnect(未知来源)的java.net.PlainSocketImpl.socketConnect(本机方法)连接超时java.net.S java.net.SocksSocketImpl.connect(未知来源)中的.AbstractPlainSocketImpl.connect(未知来源)来自java.net.Socket。(java)的java.net.Socket.connect(未知源)的ocket.connect(未知源),位于sun.rmi.transport.proxy的java.net.Socket。(未知来源)。 sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown Source)的RMIDirectSocketFactory.createSocket(Unknown Source)... 9更多

其中192.168.1.51是我的本地ip-adress(即端口转发工作正常)。

答案

好吧,我猜你的WebService是在NAT之后,你已经在1099上设置了端口转发以进入RMI注册表。这还不够。远程对象将在不同于1099的端口上进行侦听。如果没有设置端口转发到此端口,则永远不会连接,因此在double d = service.getRoot(5.0)行处有例外。

问题是哪个端口转发?如果您没有指定端口,RMI将随机选择一个高端口。但是您可以使用UnicastRemoteObject构造函数的版本指定端口。因此,您可以选择端口号,执行IRemote service = new WebService([portnumber]);并在该端口上设置端口转发。

看它是否削减它!

另一答案

好吧,我已经解决了部分问题。它是服务器存根的逻辑背后:

在服务器端,我们必须通过添加行来添加有关全局主机名的信息

System.setProperty("java.rmi.server.hostname",Util.getGlobalAddress().getHostAddress());

... Util类可能看起来像:

public class Util{

  /**
   * Finds this computer's global IP address
   * 
   * @return The global IP address, or null if a problem occurred
   */
  public static Inet4Address getGlobalAddress()
  {
    try
    {
      URLConnection uc = new URL( "http://vallentinsource.com/globalip.php" ).openConnection();
      BufferedReader br = new BufferedReader( new InputStreamReader( uc.getInputStream() ) );
      return ( Inet4Address ) InetAddress.getByName( br.readLine() );
    }
    catch( MalformedURLException e )
    {
      e.printStackTrace();
    }
    catch( IOException e )
    {
      e.printStackTrace();
    }

    return null;

  }
}

现在它在一个方向上工作,即客户端调用,如

service.printName("Pete");

在服务器端正常工作。另一方面 ...

d = service.getRoot(5.0);
System.out.println(d);

...在客户端上还没有工作。它不会引发错误,但我们没有得到结果。然而。您可以通过添加客户端ip地址/主机名来修复它:

System.setProperty("java.rmi.client.hostname", "ip.of.client.pc");

但是服务器事先无法知道所有客户端地址。无论如何:这是一种解决方法,在某些情况下可能有所帮助。

以上是关于Java RMI地址解析问题的主要内容,如果未能解决你的问题,请参考以下文章

片段(Java) | 机试题+算法思路+考点+代码解析 2023

RMI 客户端显示 java.rmi.NotBoundException 错误

JAVA RMI远程通讯

为啥应该设置 com.sun.management.jmxremote.rmi.port?

RMI是干啥用的在JAVA里面

Java TCP/IP Socket构建和解析自定义协议消息(含代码)