2016-03-07 203 views
1

我对Java RMI没有太多经验。我正在尝试实施简单的RMI通信,但遇到了问题。Java RMI客户端和远程服务器连接拒绝本地主机

这里我RMI客户

public class MainClientApplication { 

    public static final String FILE_NAME_RMI_POLICY = "rmi.policy"; 
    public static final String RMI_DOMAIN = "mydomain.net"; 
    public static final String RMI_ENDPOINT = "/MD5Decrypter"; 
    public static final String PROTOCOL = "rmi://"; 

    public static void main(String[] args) { 
     System.out.println(System.getProperty("user.dir") + File.separator + FILE_NAME_RMI_POLICY); 
     System.setProperty("java.security.policy", System.getProperty("user.dir") + File.separator + FILE_NAME_RMI_POLICY); 
     String remoteHost = String.format("%s%s%s", PROTOCOL, RMI_DOMAIN, RMI_ENDPOINT); 
     System.setSecurityManager(new SecurityManager()); 
     try { 
      ComputeEngine computeEngine = (ComputeEngine) Naming.lookup(remoteHost); 
      SwingUtilities.invokeLater(() -> new MainWindow("MD5 Decryption", computeEngine)); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 

} 

通信inerface

public interface ComputeEngine extends Remote { 
    Object executeTask(Task t) throws RemoteException; 
} 

我的服务器

public class MainServer { 
    public static final int PORT = 1099; 
    public static final String RMI_ENDPOINT = "MD5Decrypter"; 
    public static final String FILE_NAME_RMI_POLICY = "rmi.policy"; 
    public static final String RMI_DOMAIN = "mydomain.net"; 
    public static final String PROTOCOL = "rmi://"; 

    public MainServer() { 
    try { 
     System.setProperty("java.security.policy", System.getProperty("user.dir") + File.separator + FILE_NAME_RMI_POLICY); 
     //System.setProperty("java.rmi.server.hostname", RMI_IP); 
     System.setProperty("java.rmi.server.hostname", RMI_DOMAIN); 
     System.setSecurityManager(new SecurityManager()); 
     ComputeEngine computeEngine = new ComputeEngineExecutor(); 
     // Naming.rebind(String.format("%s%s:%d/%s", PROTOCOL, RMI_DOMAIN, PORT, RMI_ENDPOINT), computeEngine); 
     Naming.rebind(RMI_ENDPOINT, computeEngine); 
     System.out.println("Successfully started RMI Server"); 
    } catch (RemoteException e) { 
     e.printStackTrace(); 
    } catch (MalformedURLException e) { 
     e.printStackTrace(); 
    } 
} 

    public static void main(String[] args) { 
     MainServer mainServer = new MainServer(); 
    } 

} 

而且rmi.policy

grant { 
    permission java.net.SocketPermission "*:1024-65535", "connect, accept"; 
    permission java.io.FilePermission "-", "read"; 
    permission java.net.SocketPermission "*:80", "connect"; 
}; 

所以我在我的服务器rmiregistry 1099上启动了rmiregistry。一切都很好,直到调用远程对象方法。

这里有

让我们考虑,我的域名是mydomain.net,我使用静态IP承载它在我的服务器在家里我的脚步。在服务器上

  1. 运行rmiregistry
  2. 服务器上
  3. 运行服务器应用程序在任何PC上
  4. 运行客户端应用程序
  5. 点击按钮来调用远程方法

如此看来,一切所连接并成功绑定,因为如果强制输入无效域,端点或拒绝rmiregistry未启动 - 引发java.rmi.ConnectException

但是,当我尝试调用远程对象上的任何方法,BTW这已被检索到的成功,它抛出一个java.rmi.ConnectException

java.rmi.ConnectException: Connection refused to host: 127.0.1.1; nested exception is: 
    java.net.ConnectException: Connection refused 
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619) 
    at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216) 
    at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202) 
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:130) 
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:227) 
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:179) 
    at com.sun.proxy.$Proxy0.executeTask(Unknown Source) 
    at ui.MainWindow.lambda$initGui$0(MainWindow.java:49) 
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022) 
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348) 
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) 

,我可以理解,问题是它(服务器)迫使我连接到我的本地主机而不是远程。

P.S localhost上一切完美(客户端和服务器上的一台PC上)

请帮助解决这个问题。

编辑

我忘了告诉大家,我试图设置的java.rmi.server.hostname属性,在这种情况下,它需要大量的时间来启动服务器,并与异常结束。

+1

请参阅RMI FAQ项目A.1。 – EJP

+0

感谢您的回答,我已经尝试设置'java.rmi.server.hostname',但它奇怪地工作,它需要大量的时间来启动服务器和连接,但仍然无法工作 - 超时。 – CROSP

+1

你把它设置成什么?你必须告诉我们你做了什么。我们无法看到您的电脑。注意你必须在服务器JVM上设置* * – EJP

回答

1

抛开127.0.0.1的问题,java.rmi.server.hostname解决了,现在你的问题是连接超时。这将由您的防火墙引起。您需要将远程对象导出到特定端口,并且需要在防火墙中打开该TCP端口。

+0

谢谢你的回答。 我从外部世界(路由器)转发端口'1099'到我运行服务器的本地PC。 有趣的是,如果等待很长时间aprox。 5分钟的服务器将启动,并且客户端可以连接到它(名称查找),但是它又花费了很多时间,并且当我尝试调用远程方法时,它等待并超过5分钟或更多时间后抛出超时异常 – CROSP

+1

端口1099注册表端口。您需要另一个远程对象。否则,在您的JVM中创建注册表并为两者使用1099。超时是因为所需端口未打开。您成功连接到注册表,但不连接到远程对象。听起来像你也有一个巨大的DNS延迟。 – EJP

+0

非常感谢您的帮助,我也尝试在代码中以编程方式创建注册表,但似乎是相同的情况。 据我所知,客户端和服务器将使用随机端口相互通信,我不想打开我的路由器中的所有端口。请你可以提供任何示例如何为远程对象指定通信端口。 – CROSP

相关问题