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.


 

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

28549. Режим CBC 39 KB
  Дешифрование в режиме СВС Для получения первого блока зашифрованного сообщения используется инициализационный вектор IV для которого выполняется операция XOR с первым блоком незашифрованного сообщения. В режиме CBC при зашифровании каждая итерация алгоритма зависит от результата предыдущей итерации поэтому зашифрование сообщения не поддаётся расспараллеливанию. Однако расшифрование когда весь шифротекст уже получен можно выполнять параллельно и независимо для всех блоков сообщения см. Это дает значительный выигрыш во времени при...
28550. Режим CFB 66.5 KB
  Как и в режиме CBC здесь используется операция XOR для предыдущего блока зашифрованного текста и следующего блока незашифрованного текста. Таким образом любой блок зашифрованного текста является функцией от всего предыдущего незашифрованного текста. Для левых J битов выхода алгоритма выполняется операция XOR с первыми J битами незашифрованного текста Р1 для получения первого блока зашифрованного текста С1. При дешифровании используется аналогичная схема за исключением того что для блока получаемого зашифрованного текста выполняется...
28551. Режим шифрования с обратной связью по выходу (OFB) 52.55 KB
  Разница заключается в том что выход алгоритма в режиме OFB подается обратно в регистр тогда как в режиме CFB в регистр подается результат применения операции XOR к незашифрованному блоку и результату алгоритма см. Шифрование в режиме OFB Основное преимущество режима OFB состоит в том что если при передаче произошла ошибка то она не распространяется на следующие зашифрованные блоки и тем самым сохраняется возможность дешифрования последующих блоков. Дешифрование в режиме OFB Недостаток режима OFB заключается в том что он более уязвим к...
28552. Симметричные методы шифрования DES 63.46 KB
  Функция перестановки одна и та же для каждого раунда но подключи Ki для каждого раунда получаются разные вследствие повторяющегося сдвига битов ключа. Последовательность преобразований отдельного раунда Теперь рассмотрим последовательность преобразований используемую на каждом раунде. Создание подключей Ключ для отдельного раунда Ki состоит из 48 битов. На каждом раунде Ci и Di независимо циклически сдвигаются влево на 1 или 2 бита в зависимости от номера раунда.
28553. Примеры современных шифров проблема последнего блока DES 26.44 KB
  Альтернативой DES можно считать тройной DES IDEA а также алгоритм Rijndael принятый в качестве нового стандарта на алгоритмы симметричного шифрования. Также без ответа пока остается вопрос возможен ли криптоанализ с использованием существующих характеристик алгоритма DES. Алгоритм тройной DES В настоящее время основным недостатком DES считается маленькая длина ключа поэтому уже давно начали разрабатываться различные альтернативы этому алгоритму шифрования.
28554. Распределение ключей. Использование базовых ключей 13.15 KB
  Он заключается в доставке абоненту сети связи не полного комплекта ключей для связи со всеми другими абонентами а некоторой универсальной заготовки уникальной для каждого абонента по которой он может вычислить необходимый ему ключ. Пусть в сети связи действуют N абонентов занумеруем их от 0 до N1 и поставим каждому абоненту уникальный открытый идентификатор Yi из некоторого множества Y открытый в смысле общеизвестный. Генерация ключей для абонентов сети связи заключается в выработке N секретных ключей Xi из некоторого множества X....
28555. Использование маркантов или производных ключей 15.1 KB
  Заключается в использовании для шифрования не непосредственно ключей хранимых у абонентов а некоторых производных ключей из них получаемых. Заключается в использовании вместо ключа K двоичного вектора S полученного побитным суммированием K и случайного двоичного вектора M называемого маркантом при этом маркант передается в открытом виде отправителем получателю. Действительно использование одного и того же ключа но разных маркантов не снижает стойкости шифра. Однако этот метод обладает одним недостатком восстановление одного...
28557. Несимметричные системы шифрования и их построение 23.7 KB
  Эти системы характеризуются тем что для шифрования и для расшифрования используются разные ключи связанные между собой некоторой зависимостью. Один из ключей например ключ шифрования может быть сделан общедоступным и в этом случае проблема получения общего секретного ключа для связи отпадает. Поскольку в большинстве случаев один ключ из пары делается общедоступным такие системы получили также название криптосистем с открытым ключом. Первый ключ не является секретным и может быть опубликован для использования всеми пользователями...