0

我正在尝试重新编码一些基本的设计模式。只有代码片段可供我使用,没有完整的运行代码示例。一种称为代理模式。

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

网络服务.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)) 的签名。

现在连接到远程的类:

测试代理.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 进行检查,也无法通过 Internet 进行连接。

当我从命令行开始时:

java net.mypackage.remote.TestProxy 78.2.2.2

它总是给出结果:

试图查找服务...完成 java.rmi.ConnectException: Connection refused to host: 192.168.1.51; 嵌套的异常是: java.net.ConnectException: Connection timed out 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 own Source) at java.rmi.server.RemoteObjectInvocationHandler。在 net.gerdsmeier.remote.TestProxy.go(TestProxy.java:39) 在 net.gerdsmeier.remote.TestProxy.main(TestProxy.java:22) 在 $Proxy1.getRoot(Unknown Source) 调用(Unknown Source) : java.net。

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

4

2 回答 2

0

好的,我猜您的 WebService 在 NAT 之后,并且您已经在 1099 上设置了端口转发以通过 RMI 注册表。这还不够。远程对象将在与 1099 不同的端口上监听。如果您没有设置到该端口的端口转发,您将永远无法连接,因此该double d = service.getRoot(5.0)行出现异常。

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

看看能不能剪!

于 2012-09-26T16:07:48.407 回答
-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 地址/主机名来修复它:

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

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

于 2012-09-26T19:24:54.783 回答