2013-07-16 3 views
1

Недавно я работал с RMI, и хотя мне удалось заставить его работать на locahost, у меня возникали проблемы при попытке использовать удаленный сервер. Вот основной код, который я пытаюсь запустить:RMI не может подключиться к удаленному серверу

Сервер:

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 

Я борюсь с этими ошибками связи весь день вчера, и это насколько я добрался. Я уверен, что есть только одна очень маленькая вещь, которую я все еще делаю неправильно, но я просто не могу найти, что это такое.

+0

Можете ли вы подключиться к любому порту на удаленном компьютере, используя, например, телнет? –

+0

Да, у меня нет проблем с другими типами соединений. Я использовал порт 22, 80 или 11111 (JPPF) без проблем. – spacitron

+0

Код вашего клиента имеет другой IP-адрес из сообщения «Отказано в подключении», поэтому следующее может быть полезным: http://stackoverflow.com/questions/3071376/what-port-is-used-by-java-rmi -connection –

ответ

1

Это может не решить вашу проблему, но у меня были аналогичные проблемы с JPPF (через Java RMI) в Linux. Решение состояло в том, чтобы обеспечить, чтобы эфемерный диапазон портов на клиентской машине охватывал только порты, допустимые локальным брандмауэром на стороне клиента. Например, если ваш брандмауэр позволяет подключать порты с 48000 до 64000 с помощью внешней машины, убедитесь, что ваш эфемерный диапазон портов также находится в пределах от 48000 до 64000. Попробуйте и сообщите нам, что произойдет.

+0

+1, но Registry не «отключает соединения». Он не вызывается на этапе подключения. Что действительно происходит, так это то, что, если вы не укажете порт при экспорте удаленного объекта, он * прослушивает * на эфемерном порту. – EJP

+0

Я не говорю конкретно о реестре, я говорю о базовых сетевых механизмах, используемых для обслуживания этого реестра. Под капотом RMI использует 'ServerSocket' и' Socket'.'ServerSocket' наиболее определенно прослушивает определенный порт и после первоначального рукопожатия с клиентом передает все последующие сообщения с этим клиентом на« Socket », который прослушивает совершенно другой номер эфемерного порта, независимо от того, какой номер порта вы выбрали для прослушивания вашего «ServerSocket». – CodeBlind

+0

Вы ошибаетесь. ServerSocket возвращает сокеты, чей локальный номер порта * * тот же *, что и номер порта прослушивания. Поэтому, если вы экспортируете объект RMI на фиксированный порт, все подключения к этому объекту будут использовать этот порт. Причина, по которой эфемерные поэты появляются в RMI, заключается в том, что при экспорте, не предоставляя ненулевой номер порта, например, через super (int port). – EJP

-3
System.setProperty("java.rmi.server.hostname","10.0.3.73"); 

Используйте приведенные выше утверждения в своем боковом коде RMIServer и попробуйте снова подключиться к удаленному клиенту. Это сработало для меня

+3

Он работал на вас по этому IP-адресу, потому что это один из ваших IP-адресов. Ничего об этом не гарантируется для всех. – EJP