【问题标题】:RMI ConnectException : Connection refused, really strange behaviourRMI ConnectException:连接被拒绝,非常奇怪的行为
【发布时间】:2012-12-09 21:27:41
【问题描述】:

我知道这个问题已经被问过好几次了,但我还没有找到适合我的答案。基本上我已经用 RMI 实现了一个客户端/服务器解决方案。我唯一的问题是与服务器的连接有时非常慢。

当服务器启动并且客户端第一次连接时,它需要几秒钟才能连接(有时它甚至不连接而是得到 ConnectException),之后我会在尝试时得到连接被拒绝与服务器通信。 更令人难以置信的是,当我断开第一个失败的客户端并再次连接时,它工作得非常好。然后客户端在一秒钟内连接,所有通信都完美无缺。

我已经尝试手动启动 rmiregistry,我已经仔细检查了我的 PATH。我无法使用 telnet 连接到该端口,但是当我在该端口上玩我的 Othello 游戏(未使用 RMI)时它可以工作。值得一提的是,我在同一网络和计算机上执行此操作,因此我使用的是 localhost。

TL;DR:当我第一次连接到服务器时,它需要很长时间,但我能够连接。然后当我尝试与它崩溃的方法通信时,我收到“java.rmi.ConnectException:连接拒绝主机:192.xxx.xxx.x;嵌套异常是: java.net.ConnectException: Connection timed out: connect"。如果我随后关闭该客户端并尝试与另一个客户端连接,则连接大约需要一秒钟,然后一切正常。为什么会这样?

客户端代码:

public class NetworkClient {
private Registry registry;
private IArenaServer server;

public NetworkClient(String ipAddress, int port) throws RemoteException {

    if (System.getSecurityManager() == null) {
        System.setSecurityManager(new RMISecurityManager());
    }

    try {

        registry = LocateRegistry.getRegistry(ipAddress, port);
        server = (IArenaServer)(registry.lookup("arenaServer"));
        System.out.println("Client successfully connected to server at " + ipAddress + ":" + "port");

    } catch (NotBoundException ex) {
        Logger.getLogger(NetworkClient.class.getName()).log(Level.SEVERE, null, ex);
    } catch (AccessException ex) {
        Logger.getLogger(NetworkClient.class.getName()).log(Level.SEVERE, null, ex);
    }
}

服务器代码:

public class ArenaServer extends UnicastRemoteObject implements IArenaServer {

private int port = 9029;
private String ipAddress;
private Registry registry;

public ArenaServer() throws RemoteException {

    if(System.getSecurityManager() == null){
        System.setSecurityManager(new RMISecurityManager());
    }

//  try {
        //ipAddress = (InetAddress.getLocalHost()).toString();
        registry = LocateRegistry.createRegistry(port);
        registry.rebind("arenaServer", this);

        System.out.println("Server successfully started...");
        //System.out.println("Server's IP address is: " + ipAddress);

//  } catch (UnknownHostException ex) {
//      ErrorHandler.getInstance().reportError("Cannot get IP address", "");
//  }
}

第一次连接后尝试与服务器通信时得到的一般示例:

java.rmi.ConnectException: Connection refused to host: 192.xxx.xxx.x; nested exception is: 
java.net.ConnectException: Connection timed out: connect
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(Unknown Source)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)
at $Proxy0.getInstalledGames(Unknown Source)
....

【问题讨论】:

  • 这里没有“连接到服务器”步骤。到目前为止,您所做的只是连接到注册表并进行查找。如果您收到拒绝连接,则说明您有防火墙问题或注册表未运行。您发布的服务器代码无法编译。如果您遇到其他类型的 ConnectException,您需要告诉我们它是什么。
  • 没有“连接到服务器”步骤是什么意思?我可以连接到服务器,但第一次真的很慢/崩溃。当您关闭失败的客户端并连接新的客户端时,它可以完美运行。我已经向服务器和客户端添加了更多代码,这应该使它更清晰一些。当我在 jre\bin 中启动 rmiregistry.exe 时,我也会遇到同样的错误。 Windows 防火墙已关闭。
  • 我已经说过我的意思了。当您通过远程存根调用服务器上的远程方法时,会发生连接步骤:您上面的代码没有这样做。
  • 我明白了,如果我误解了你,对不起。好吧,基本上当我通过存根调用远程方法时会发生错误。我在做 List installedGames = frameController.getServer().getInstalledGames();其中 getInstalledGames 是远程方法,getServer 返回存根。

标签: java rmi


【解决方案1】:

这听起来像是 java.rmi.server.hostname 的情况。请参阅 RMI 常见问题解答中的 A.1 项,可通过 RMI 主页访问。

【讨论】:

  • 我在服务器的运行配置中添加了 -Djava.rmi.server.hostname=ExternalIpHere,现在它的连接速度更快了。虽然我在尝试调用远程方法时仍然收到“连接被拒绝”错误。
  • @Oakin 连接超时表示网络拓扑问题,而不是编码问题。检查客户端和服务器之间是否有干净的 IP 路由;检查 ping 时间;检查您是否可以从客户端远程登录到服务器上的相应端口;检查客户端和服务器上的防火墙、iptables 等规则; ...
  • 是的,我很确定我的代码没有任何问题。我今天在不同的网络上尝试了该应用程序,但它没有工作。我的朋友在他的地方尝试过,对他来说效果很好。所以是我的电脑或他的网络有问题?
  • forums.oracle.com/forums/thread.jspa?messageID=10220096 的测试在两个地址都给我 null 可能会有所帮助
  • @Oakin 那会是什么测试?我为该线程做出了贡献。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 2011-07-01
  • 2012-09-10
相关资源
最近更新 更多