RMI 无法连接到远程服务器
Posted
技术标签:
【中文标题】RMI 无法连接到远程服务器【英文标题】:RMI cannot connect to remote server 【发布时间】:2013-07-16 16:22:29 【问题描述】:我最近一直在使用 RMI,虽然我设法让它在 locahost 上工作,但在尝试使用远程服务器时遇到了各种各样的问题。这是我要运行的基本代码:
服务器:
public class RmiServer extends UnicastRemoteObject implements RmiServerIntf
public static final String MESSAGE = "Hello world";
public RmiServer() throws RemoteException
public String getMessage()
return MESSAGE;
public static void main(String args[])
System.out.println("RMI server started");
if (System.getSecurityManager() == null)
System.setSecurityManager(new RMISecurityManager());
System.out.println("Security manager installed.");
else
System.out.println("Security manager already exists.");
try
LocateRegistry.createRegistry(1099);
System.out.println("java RMI registry created.");
catch (RemoteException e)
e.printStackTrace();
try
RmiServer obj = new RmiServer();
Naming.rebind("rmi://localhost/RmiServer", obj);
System.out.println("PeerServer bound in registry");
catch (Exception e)
e.printStackTrace();
远程类接口:
public interface RmiServerIntf extends Remote
public String getMessage() throws RemoteException;
客户:
public class RmiClient
RmiServerIntf obj = null;
public String getMessage()
try
obj = (RmiServerIntf)Naming.lookup("rmi://54.229.66.xxx/RmiServer");
return obj.getMessage();
catch (Exception e)
e.printStackTrace();
return e.getMessage();
public static void main(String args[])
if (System.getSecurityManager() == null)
System.setSecurityManager(new RMISecurityManager());
RmiClient cli = new RmiClient();
System.out.println(cli.getMessage());
rmi.policy 文件:
grant
permission java.security.AllPermission;
;
我编译了这些类并为服务器创建了一个存根。然后我将客户端、存根、接口和策略放在我的机器上,将服务器、存根、接口和策略放在远程机器上。远程服务器是一台 Linux 机器,我使所有文件都可执行。我还在本地防火墙上添加了一条允许端口 1099 的规则,并打开了远程机器上的所有端口
之后,我导航到远程机器上的服务器目录并插入以下命令:
java -Djava.security.policy=rmi.policy RmiServer
这并没有给我带来问题,所以我回到本地机器并进入了
java -Djava.security.policy=rmi.policy RmiClient
我等待,等待,然后我收到错误消息:
Connection refused to host: 172.31.xx.xx; nested exception is: java.net.ConnectException: Connection timed out: connect
我昨天整天都在与这些连接错误作斗争,这就是我所得到的。我确信只有一件非常小的事情我仍然做错了,但我就是找不到它是什么。
【问题讨论】:
您可以使用例如连接到远程计算机上的任何端口吗?远程登录? 是的,我对其他类型的连接没有任何问题。我使用端口 22、80 或 11111 (JPPF) 没有问题。 您的客户端代码与“连接被拒绝”消息的 ip 地址不同,因此以下内容可能会有所帮助:***.com/questions/3071376/… 【参考方案1】:这可能无法解决您的问题,但我在 Linux 上遇到了与 JPPF(通过 Java RMI)类似的问题。解决方案是确保客户端机器上的临时端口范围仅覆盖客户端本地防火墙允许的端口。例如,如果您的防火墙允许外部计算机连接端口 48000 到 64000,请确保您的临时端口范围也在 48000 到 64000 之间。试一试,让我们知道会发生什么。
【讨论】:
+1 但注册表根本不会“移交连接”。它不在连接阶段调用。真正发生的是,除非您在导出远程对象时指定端口,否则它会在临时端口上侦听。 我不是专门谈论注册表,我是在谈论用于为该注册表提供服务的底层网络机制。在底层,RMI 使用ServerSocket
和Socket
。 ServerSocket
肯定会侦听特定端口,并且在与客户端进行初始握手后,将与该客户端的所有后续通信移交给Socket
,该Socket
侦听完全不同的临时端口号,无论您选择什么端口号让您的ServerSocket
继续收听。
你错了。 ServerSocket 返回本地端口号与侦听端口号相同的 Sockets。因此,如果您在固定端口上导出 RMI 对象,则到该对象的所有连接都将使用该端口。临时诗人出现在 RMI 中的原因是因为在导出时没有提供非零端口号,例如通过超级(int 端口)。
确实是我的错。我第一次接触 RMI 是在一个使用自定义 ServerSocket 和 Socket 工厂的项目中,这些工厂以我描述的“移交”方式行事——我们这样做是为了让对手更难劫持特定的客户端连接——但它一直一段时间,所以我把它误认为是默认的 RMI 行为。
我看不出这怎么可能,除非您在临时端口上使用额外的侦听套接字。我建议你的回忆也是错误的。我也建议你修正你的答案。【参考方案2】:
System.setProperty("java.rmi.server.hostname","10.0.3.73");
请在您的 RMIServer 端代码中使用上述语句,然后再次尝试从远程客户端连接。它对我有用
【讨论】:
它在该 IP 地址上为您工作,因为这是您的 IP 地址之一。没有什么可以保证对每个人都有效。以上是关于RMI 无法连接到远程服务器的主要内容,如果未能解决你的问题,请参考以下文章