63315

Удаленный интерфейс. Remote Method Invocation

Лекция

Информатика, кибернетика и программирование

Традиционный подход к выполнению на удаленной машине сбивал с толку, а также был утомителен и подвержен ошибкам при реализации. Лучший способ представить эту проблему – это думать, что какой-то объект живет на другой машине, и что вы можете посылать сообщения удаленному объекту и получать результат, будто бы объект живет на вашей машине.

Русский

2014-06-19

66.5 KB

1 чел.

  1.  Remote Method Invocation    

Традиционный подход к выполнению на удаленной машине сбивал с толку, а также был утомителен и подвержен ошибкам при реализации. Лучший способ представить эту проблему – это думать, что какой-то объект живет на другой машине, и что вы можете посылать сообщения удаленному объекту и получать результат, будто бы объект живет на вашей машине. Говоря простым языком, это в точности то, что позволяет делать Удаленный вызов методов  (Remote Method Invocation - RMI) Java.

Удаленный интерфейс

RMI большей частью использует интерфейсы. При создании своего удаленного объекта вы скрываете его низкоуровневую реализацию, передавая ссылку на его интерфейс. Таким образом, когда удаленный клиент получает ссылку на объект, на самом деле он получает ссылку на интерфейс, который по некоторой причине оказывается подсоединенным к локальному коду – “заглушке”, который и производит переговоры по сети. Но вы не заботитесь об этом, вы просто посылаете сообщения через ссылку на  интерфейс.    

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

  1.  Удаленный  интерфейс должен быть открытым – public (он не должен иметь “доступ на уровне пакета”, так же он не может быть “дружественным”). В противном случае клиенты будут получать ошибку при попытке загрузки удаленного объекта, реализующего удаленный  интерфейс.
  2.  Удаленный  интерфейс должен расширять интерфейс, java.rmi.Remote.
  3.  Каждый метод удаленного интерфейса должен объявлять java.rmi.              RemoteException в своем предложении throws вдобавок к любым исключениям, специфичным для вашего приложения.
  4.  Удаленный объект, передаваемый как аргумент или возвращаемое значение (прямо или косвенно как объект – член локального объекта), должен быть объявлен как удаленный  интерфейс, а не как класс с реализацией.
Ниже приведен простой удаленный  интерфейс, представляющий сервис точного времени:
import java.rmi.* ;
interface PerfectTimeI extends Remote {
        long  getPerfectTime () throws RemoteException;
Он выглядит как любой другой интерфейс, за исключением того, что расширяет  другой интерфейс Remote и все его методы выбрасывают RemoteException. Помните, что интерфейс и все его методы автоматически становятся public.
 
Реализация удаленного  интерфейса
Сервер должен содержать класс, который расширяет UnicastRemoteObject и реализует удаленный  интерфейс. Этот класс также может иметь другие методы, но для клиента доступны только методы удаленного  интерфейса, так как клиент получает ссылку только на удаленный  интерфейс, а не на класс, который его реализует.
Вы должны явно определить конструктор для удаленного объекта, даже если вы определяете конструктор по умолчанию, который вызывает конструктор базового класса. Вы должны написать его, так как он должен выбрасывать RemoteException.
Ниже приведена реализация удаленного интерфейса PerfectTimeI:
import  java.rmi.* ;
import  java.rmi.server.* ;
import  java.rmi.registry.* ;
import  java.rmi.net.* ;
public class PerfectTime extends UnicastRemoteObject implements PerfectTimeI {
         // Реализация интерфейса:
        public long getPerfectTime () throws  RemoteException {
                 return System.currentTimeMillis ();
        }
        //  Должна быть реализация конструктора
        //  для выбрасывания RemoteException :
      public PerfectTime () throw RemoteException {
                // super (); // вызывается автоматически
      }
      //  Регистрация для обслуживания RMI. Выбрасывает 
      //  исключения на консоль.
      Public static void main (String [] args) throws  Exception {
               System.setSecurityManager (new RMISecurityManager ());
               PerfectTime pt = new PerfectTime ();
               Naming.bind (“//Ready to do time”);
      }
 }
В   этом примере main () обрабатывет все установки сервера. Когда вы обслуживаете RMI объект, в определенном месте вашей программы вы должны:
  1.  Создать и установить менеджер безопасности, поддерживающий сервисы RMI. Как часть Java пакета, для RMI поддерживается только RMISecurityManager.
  2.  Создать один или несколько экземпляров удаленного объекта. Здесь вы видите создание объекта PerfectTime.
  3.  Зарегистрировать не менее одного удаленного объекта в реестре удаленных объектов RMI, чтобы в последствии ими можно было пользоваться. Этот удаленный объект может иметь методы, которые производят ссылки на другие удаленные объекты. Их также можно зарегистрировать в реестре, чтобы клиенту не пришлось обращаться к нему много раз.
Установка реестра
В рассмотренном примере вызывался статический метод Naming.bind(). Однако для вызова этого метода требуется, чтобы реестр был запущен отдельным процессом на вашем компьютере. Имя сервера реестра – это rmiregistry, и для запуска под 32-битной Windows необходимо выполнить следующую команду:
start rmiregistry
              port 1099
для запуска его в качестве фонового процесса или  start rmiregistry 2005
Как и многие другие сетевые программы, сервер rmiregistry располагается по IP адресу машины, с которой его установили, но он также должен прослушивать порт под определенным порядковым номером. Если вы вызовите rmiregistry как показано выше, без аргументов, будет использован порт по умолчанию 1099. Если вы хотите использовать другой порт, вы добавляете аргумент в командную строку, указывающий порт. Следующий пример устанавливает порт 2005, поэтому rmiregistry под управлением 32-битной Windows должен запускаться так:
start rmiregistry 2005
Информацию о порте также необходимо передать в метод bind(), наряду с IP адресом машины, где располагается сервер реестра. Но при попытке использовать локальный IP-адрес, как это делается при тестировании сетевых программ, возникает досадная проблема. В JDK 1.1.1 существовала пара таких проблем:
  1.  Локальный IP-адрес localhost не работает с библиотекой RMI. Поэтому для экспериментов с RMI на одной машине вы должны использовать настоящее имя машины.
  2.  Библиотека RMI не станет функционировать, пока у вас не будет настоящего TCP/IP соединения, даже если все ваши компоненты просто общаются друг с другом на одной машине. Это значит, что вы должны соединиться с вашим Internet-провайдером до того, как попробуете запустить программу, иначе возникнут странные сообщения об ошибках.
Если учесть все это, команда bind () примет вид:
Naming.bind (“//peppy: 2005/PerfectTime”, pt);

Если вы используете порт по умолчанию 1099, вам не нужно указывать порт, так что вы можете просто сказать:

Naming.bind("//peppy/PerfectTime", pt);

Вы можете выполнить локальную проверку оставив в покое IP адрес, а использовать только идентификатор:

Naming.bind("PerfectTime", pt);

Имя сервиса здесь произвольно. В данном случае PerfectTime выбрано просто как имя класса, но вы можете назвать так, как захотите. Важно, чтобы это было уникальное имя регистрации, чтобы клиент знал имя, когда будет искать определенный удаленный объект. Если имя уже зарегистрировано, вы получите AlreadyBoundException. Чтобы предотвратить это, вы всегда можете использовать rebind () вместо bind (), так как rebind () либо добавляет новый элемент, либо заменяет уже существующий.

Даже после завершения работы main(), ваш объект остается существовать в реестре, ожидая, что придет клиент и выполнит запрос. Пока rmiregistry остается запущенным, и вы не вызовите Naming, unbind () на вашей машине, объект будет оставаться там. По этой причине, при отладке вашего кода необходимо выгружать rmiregistry и перезапускать его, когда скомпилируете новую версию вашего удаленного объекта.

Вам не обязательно запускать rmiregistry как внешний процесс. Если вы знаете, что только ваше приложение использует регистрацию, вы можете загрузить ее внутри вашей программы с помощью строки:

 LocateRegistry.createRegistry(2005);

Как и раньше, 2005 - это номер порта, который использовался в этом примере. Это эквивалентно запуску rmiregistry 2005 из командной строки, но часто этот способ является более удобным при разработке RMI-приложений, так как это снижает число необходимых действий при запуске и остановке реестра. После того, как вы выполните этот код, вы можете вызвать Naming. bind (), как и ранее.

Создание заглушек и каркасов

Если вы откомпилируете и запустили PerfectTime . Java, оно не будет работать, даже если вы правильно запустили rmiregistry. Это происходит потому, что основного каркаса библиотеки RMI еще не создано. Вы должны сначала создать заглушки и каркасы, которые обеспечат работу сетевого соединения и позволят вам делать вид, что удаленный объект - это просто локальный объект на вашей машине.

То, что происходит за сценой - очень сложно. Любой объект, который вы передаете или получаете из удаленного объекта, должен реализовывать(1тр!етеп1) Serializable (если вы хотите передавать удаленные ссылки вместо целых объектов, аргументы объектов могут реализовывать Remote), так что вы можете представить, как заглушки и каркасы автоматически выполняют сериализацию и десериализацию во время | «упаковки» параметров методов и возвращаемых результатов. К счастью, вам не нужно знать всего этого, но вы должны создавать заглушки и каркасы. Это простой процесс: вы вызываете инструмент rmic для вашего откомпилированного кода, а он создает необходимые файлы. Так что от вас требуется включить еще один шаг в процесс компиляции.

PerfectTime.java находится в пакете clS.rmi:

rmic c!5.rmi.PerfectTime

Вам не нужно быть в директории, содержащей PerfectTime. class, когда вы исполняете эту команду, но результат будет помещен в текущий директорий (из которого вы запустили команду).

Когда выполнение программы rmic завершится успешно, вы найдете два новых класса в директории:

PerfectTime_Stub.class

PerfectTime_Skel.class

соответствующих заглушке и каркасу. Теперь вы готовы запустить общение клиента с сервером.

Использование удаленных объектов

Главная цель RMI состоит в упрощении использования удаленных объектов. Вы должны сделать только самую важную вещь в вашей клиентской программе: это поиск и получение удаленного интерфейса с сервера. Во всем остальном - это обычное программирование на Java: посылка сообщений объекту. Ниже приведена программа, использующая PerfectTime:

import java.rmi.*;

import Java . rmi . registry .*;

public class DisplayPerfectTime {

           public static void main (String [] args) throws Exception {

           System.setSecurityManager (new RMISecurityManager ()) ;

             PerfectTimel t = (PerfectTimel ) Naming. lookup (

     "//peppy: 2005/PerfectTime") ;

for(int i = 0; i < 10; i++)

                  System. out . println ( "Perfect time = " +

                        t . getPerf ectTime (

                }

        } ;

Использованный идентификатор совпадает с тем, что использовался при регистрации объекта в реестре помощью Naming, а первая часть представляет URL и номер порта. Так как вы используете URL, вы можете также указать любую машину в Internet.

То, что возвращается из Naming, lookup () должно быть преобразовано к удаленному интерфейсу, а не к классу. Если вы будите использовать класс, вы получите исключение.

Вы можете видеть, что вызов удаленного метода

t.getPerfectTime ( )

ничем не отличается от вызова метода любого локального объекта. Как только вы получаете ссылку на удаленный объект, программирование с ним ничем не отличается от программирования с локальными объектами (за одним исключением: удаленные методы способны возбуждать исключение RemoteException.


 

А также другие работы, которые могут Вас заинтересовать

73805. Основные направления западной философии конца XIX-XX веков 123 KB
  Основные направления западной философии конца XIX-XX веков. Основными тенденциями в развитии современной философии выступают сциентизм и антропологизм. Первая проявляется в позитивизме философии науки структурализме и других. Необходимо также отметить что тенденции к ограничению теоретического разума отчетливо проявлялись в недрах самой классической философии.
73806. Русская философия 104.5 KB
  Исследователи неоднократно отмечали что самое оригинальное и значительное было создано русскими мыслителями в области философии истории историософия и социальной философии. Высокая духовность обоснование нравственности как необходимого условия человеческого бытия – важнейшая черта русской философии неизменный вектор многовековой социокультурной традиции. Кажется что грани этой вечной проблемы во многом определяют напряженное поле отечественной культуры и философии стремящихся определить свое собственное место в лоне мировой цивилизации....
73807. Учение о бытии (онтология) 84.5 KB
  Исторические корни возникновения понятия бытия. В европейской культуре первые определения бытия возникли еще в Древней Греции что исторически совпало со становлением философского знания переходом от образномифологического к теоретикологическому мышлению. Понятие бытия отвлекается от бесконечного многообразия свойств и качеств конкретных предметов кроме одного быть существующими. Исторические корни возникновения понятия бытия Бытие производное от слов быть есть весьма распространенных во многих языках мира имеет свое...
73808. Учение о развитии. Диалектика 113 KB
  Диалектика – теория и метод познания действительности, учение о всеобщей связи и развитии. Представления об изменчивости и взаимосвязанности всего сущего возникли в глубокой древности.
73809. Сознание. Современные представления о сознательной деятельности 95 KB
  Историческое развитие понятия сознания. Проблема сознания во все века привлекала внимание философов ибо она рассматривает одну из наиболее значимых и специфических сторон человеческой жизнедеятельности. В истории философии существуют различные иногда диаметрально противоположные точки зрения объясняющие сущность сознания его происхождение и роль в обществе. В современной отечественной философии возобладающим является понимание сознания как идеальной формы деятельности направленной на отражение и преобразование действительности.
73810. Познание. Познавательные способности человека 95.5 KB
  Теория истины. Центральной проблемой гносеологии является проблема истины под которой понимается соответствие знаний действительности. В качестве основного критерия истины признак по которому определяется достоверность знания выступает деятельность человека понятая как общественно-историческая практика. Интуиция – это способность постижения истины без развернутого логического обоснования в ее непосредственности как единство чувственного и рационального.
73812. Человек как объект философского осмысления 100.5 KB
  Историческое развитие взглядов на человека. При всем различии взглядов на сущность человека его личностные качества анализируются подавляющим большинством философов через деятельность индивида направленную на окружающий мир. Историческое развитие взглядов на человека Размышления о человеке возможностях его деятельности ценностносмысловой ориентации надеждах на будущее составляют основное содержание философии. Начиная с древнейших времен возникает проблема человека заключающая неисчерпаемое многообразие аспектов и подходов своего...
73813. Культура Цивилизация Будущее человечества 128 KB
  Феномен культуры. Уровень культуры содержание особенности проявляются в объектах материальных и духовных создаваемых людьми в процессе этой деятельности. Понятие культуры означает специфический способ жизнедеятельности человека направленной на преобразование природы общества самого себя и представленной предметами материального и духовного труда. Понятие цивилизация часто используется для обозначения материальной культуры и особенно техникотехнологической основы современные орудия производства технологии компьютерноинформационные...