2009-07-22 2 views
1

Поскольку я не хотел реализовывать протокол связи для своего приложения на основе клиент-сервер, я реализовал клиент RMI и сервер RMI с обеих сторон для обмена информацией между этими двумя компонентами.Как мне настроить среду RMI, чтобы я мог использовать ее в «реальной» сети?

Если я попытаюсь использовать свое приложение, запустив два компонента на одном компьютере, все работает нормально. Но если я разбиваю компоненты на два разных компьютера (Kubuntu 9.04 внутри как виртуальная машина в среде Windows 7 RC с отключенным брандмауэром и родной средой Ubuntu 9.04), похоже, что клиент RMI не может выполнять методы, которые определенных на стороне сервера. (Каждый вызов функции приводит к исключению RMI.)

В настоящее время я установил системное свойство «java.rmi.server.hostname» с обеих сторон на сетевой интерфейс, который должен использоваться для обмена данными и зарегистрирован по умолчанию порт для связи с демоном rmi (?) rmid.

Есть ли у кого-нибудь идеи, что может произойти неправильно? Должен ли я устанавливать некоторые другие параметры, такие как «java.rmi.server.codebase» (http://java.sun.com/j2se/1.4.2/docs/guide/rmi/javarmiproperties.html), чтобы иметь возможность использовать функциональность RMI в моем приложении?

Edit: Хорошо, вот некоторая дополнительная информация для вас:

В фазе инициализации мой клиент пытается установить соединение с сервером RMI серверного компонента, который был инициализирован с помощью следующих двух методов:

private void initialize() 
{ 
    // set ip address of rmi server 
    System.setProperty("java.rmi.server.hostname", ipAddress); 

    // try to register rmi server 
    try 
    { 
     LocateRegistry.createRegistry(Registry.REGISTRY_PORT); 
    } 
    catch (Exception e) 
    { 
     // ignore 
    } 
} 

public void start() 
{ 
    System.out.print("starting master control RMI server ..."); 

    try 
    { 
     Naming.rebind("MasterControl", this); 
    } 
    catch (Exception e) 
    { 
     System.out.println("error: could not initialize master control RMI server"); 
     System.exit(1); 
    } 

    // set running flag 
    isRunning = true; 

    System.out.println(" done"); 
} 

«ipAddress» - это IP-адрес сетевого интерфейса серверного компонента.

Метод, который используется клиентским компонентом для установления соединения выглядит следующим образом:

public void connect() 
{ 
    // build connection url 
    String url = "rmi://" + masterControlIpAddress + "/MasterControl"; 

    System.out.println(url); 

    System.out.print("connecting to master control ..."); 

    // try to connect to master control server 
    while (connection == null) 
    { 
     try 
     { 
      connection = (MasterControlInterface) Naming.lookup(url); 
      id = connection.register(localIpAddress); 
     } 
     catch (Exception e) 
     { 
      // ignore 
     } 

     if (connection == null) 
     { 
      try 
      { 
       Thread.sleep(100); 
      } 
      catch (InterruptedException e) 
      { 
       e.printStackTrace(); 
      } 
     } 
    } 

    System.out.println(" done"); 
} 

Как вы можете видеть, что мой клиент вызывает функцию, чтобы зарегистрировать соединение на сервере:

@Override 
public int register(String ipAddress) throws RemoteException 
{ 
    // add connection to registrationHandler 
    masterControl.registrationHandler.addConnection(ipAddress); 

    // log 
    int connectionCount = masterControl.registrationHandler.getConnectionCount(); 
    System.out.println("slave control (" + ipAddress + ") instance has been registered at the master control server under the following id: " + connectionCount); 

    return connectionCount; 
} 

Если я запускаю свою программу с использованием реального сетевого соединения, текст «подчиненный элемент управления ...» не отображается на стороне сервера. Поэтому я не уверен, если функция действительно вызвана клиентским компонентом.

После того, как клиентский компонент происходит инициализация пытается уведомить компонент сервера, вызвав следующий метод, используя его RMI подключения к серверу:

public void sendInitializationDone() 
{ 
    try 
    { 
     connection.initializationDone(); 
    } 
    catch (RemoteException e) 
    { 
     System.out.println("error: could not send 'initializationDone' message to master control"); 
     System.out.println(e); 
     System.exit(1); 
    } 
} 

установить флаг на стороне сервера.

Ошибка внутри этой встречается, функции на стороне клиента:

java.rmi.ConnectException: Соединение отказался принять 127.0.1.1; Вложенное исключение: java.net.ConnectException: соединение отклонено.

Я понятия не имею, почему хозяин находится здесь 127.0.1.1 ...

@nos

Конечно, я отключил брандмауэр Windows и защиты mechanismn в Kaspersky Internet Security. Я не думаю, что в моем Kubuntu работает брандмауэр.В общем случае можно установить соединение, потому что я уже использовал scp для копирования моей программы на другую машину.

Edit2:

Mhhh, после установки записи в/и т.д./хостов, который относится к машине с IP-адресом машины, кажется, работает, но на самом деле не понимаю, почему это делает ...

BR,

Markus

+2

Исключение RMI было бы приятно видеть. –

+0

Прежде всего, вставьте исключение, которое вы получите, так как это скажет, что не удается. Я предполагаю, что вы уже подтвердили, что у вас есть базовая сеть между хостом и виртуальной машиной? Убедитесь, что kubuntu и машина Windows не настроены с помощью какого-либо брандмауэра. – nos

+0

Думаю, нам нужна дополнительная информация. –

ответ

5

Вам нужно добавить запись в hosts file машин, содержащих запись вида

machinename privateip 

например

virtualmachine 192.168.1.16 

Это предотвратит RMI от отправки имени хоста localhost как «Перезвони мне» адрес.

Чтобы проверить этот подход, запустите следующий код до и после выполнения изменения.

System.out.println(java.net.InetAddress.getLocalHost()); 

Он должен выдать локальный адрес перед изменениями и нелокальный адрес после изменений.

+0

Mhhh, вы правы. Если я установил эту запись, все будет работать нормально, но я думаю, что это может быть только обходным путем. Есть ли у вас какие-либо идеи, почему невозможно установить адрес «call me back», используя свойство «java.rmi.server.hostname»? – Markus

+1

Нет, не знаю. При этом, после использования RMI в производстве, я предпочел бы вместо этого что-то другое - конфигурация немного жесткая, чтобы получить правильное решение. И устаревшие RMI-заглушки управляют ;-) –

+0

Я должен был сделать это на сервере pc? У меня уже есть раскомментированная строка «127.0.0.1 localhost» в файле моих хостов. Мне нужно было удалить это? –

-2

Используя различные версии JDK на каждом сервере может вызвать эту проблему.

Используйте команду java -version , чтобы убедиться, что вы используете ту же самую версию jre.

+0

Нет, с обеих сторон есть одно и то же JRE установлен пакет (ВС-java6-JRE): ява версия "1.6.0_14" Java (TM) SE Runtime Environment (сборка 1.6.0_14-B08) Java HotSpot (TM) Клиентская VM (сборка 14.0-b16, смешанный режим, совместное использование) – Markus

+0

Этот ответ вздор. Использование разных версий JDK не приводит к отказам в подключении. – EJP

Смежные вопросы