Java RMI地址解析问题

时间:2012-09-26 15:22:48

标签: java design-patterns 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))。

现在连接到遥控器的类:

TestProxy.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:连接超时           at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source)           at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)           at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source)           at sun.rmi.server.UnicastRef.invoke(Unknown Source)           at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unkn   自己的来源)           at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)           在$ Proxy1.getRoot(未知来源)           在net.gerdsmeier.remote.TestProxy.go(TestProxy.java:39)           at net.gerdsmeier.remote.TestProxy.main(TestProxy.java:22)引起:java.net.ConnectException:连接超时           at java.net.PlainSocketImpl.socketConnect(Native Method)           at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)           at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)           在java.net.AbstractPlainSocketImpl.connect(未知来源)           在java.net.SocksSocketImpl.connect(未知来源)           在java.net.Socket.connect(未知来源)           在java.net.Socket.connect(未知来源)           在java.net.Socket。(未知来源)           在java.net.Socket。(未知来源)           at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(Unknown S   乌尔斯河)           at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown S   乌尔斯河)           ... 9更多

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

2 个答案:

答案 0 :(得分:0)

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

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

看看它是否会削减它!

答案 1 :(得分:-1)

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

在服务器端,我们必须通过添加行

来添加有关全局主机名的信息
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 adress / hostname来修复它:

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

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