Реализация почтового клиента и сервера на основе CORBA
Реализация почтового клиента и сервера на основе CORBA
11 Факультет «Информатика и системы управления» Методические указания к лабораторной работе по курсу «Распределенные системы обработки информации» "Реализация почтового клиента и сервера на основе CORBA" Москва, 2004 г. Цель работы
1. Познакомиться с технологией CORBA. 2. Познакомиться с языком IDL и описанием интерфейсов. 3. Освоить классы библиотеки org.omg. 4. Применить полученные знания на практике 1. Задание для домашней подготовкиОзнакомиться с теоретическим материалом, представленным в приложениях к данным методическим указаниям и примерами программ. Ознакомиться с текстом задания к лабораторной работе, предложить размещение компонентов и функциональность, удовлетворяющую требованиям задания к лабораторной работе, и написать программу.2. Задание к лабораторной работеРазработать почтовый клиент и сервер. Клиент - оконное приложение, которое будет позволять отсылать и получать с сервера сообщения. Идентификация клиентов на сервере, протокол передачи сообщений - на усмотрение студентов.Сервер может быть консольным приложением. Хранить сообщения можно в текстовом файле. Рекомендуется сделать сервер многопоточным.Для взаимодействия клиента и сервера использовать технологию CORBA.В качестве дополнения предлагается сервер или клиент реализовать не на Java.3. Содержание отчетаОтчет должен содержать: Постановку задачи, решаемой отлаженной программой. Руководство пользователя отлаженной программы, содержащее описание интерфейсов всех функций программы. Листинг программы с необходимыми комментариями. 4. Контрольные вопросы1. Что такое CORBA? 2. Что такое IDL? Для чего он нужен? 3. Как осуществляется взаимодействие клиента и сервера в CORBA? 4. Как передаются данные между ними? 5. Для чего нужен сервер имен? 6. Как запускается CORBA_сервер? 5. Литература1. Кен Арнольд, Джеймс Гослинг, Дэвид Холмс. Язык программирования Java™. 2. Официальный сайт Java - http://java.sun.com/ (есть раздел на русском языке с учебником). 3. Java™ 2 SDK, Standard Edition Documentation - http://java.sun.com/products/jdk/1.5/index.html. 4. Джеймс Гослинг, Билл Джой, Гай Стил. Спецификация языка Java (The Java Language Specification - http://www.javasoft.com/docs/books/jls/). Перевод на русский язык - http://www.uni-vologda.ac.ru/java/jls/index.html 5. Официальный сайт проекта Eclipse - http://www.eclipse.org/. 6. Приложение 1. CORBAТехнология CORBA (Common Object Request Broker Architecture) - это стандарт написания распределенных приложений, предложенный консорциумом OMG (Open Management Group). Создавая CORBA_объекты, мы можем, например, существенно уменьшить время решения задач, требующих выполнения большого объема вычислений. Это возможно благодаря размещению CORBA_объектов на разных машинах. Каждый удаленный объект решает определенную подзадачу, тем самым разгружает клиент от выполнения лишней работы.Основу CORBA составляет объектный брокер запросов (Object Request Broker). ORB управляет взаимодействием объектов в распределенной сетевой среде. IIOP (Internet Inter-ORB Protocol) - это специальный протокол взаимодействия между ORB.В адресном пространстве клиента функционирует специальный объект, называемый заглушкой (stub). Поучив запрос от клиента, он упаковывает параметры запроса в специальный формат и передает его серверу, а точнее скелету.Скелет (skeleton) - объект, работающий в адресном пространстве сервера. Получив запрос от клиента, он распаковывает его и передает серверу. Также скелет преобразует ответы сервера и передает их клиенту (заглушке).Для того чтобы написать любое приложение CORBA используя технологию Java, необходимо иметь две вещи - это установленный пакет JDK1.5 и компилятор idlj (…\jdk1.5.0\bin\idlj.exe). JDK предоставляет набор классов для работы с CORBA объектами, а idlj производит отображение языка IDL в Java.6.1 Создание простейшего CORBA-приложения6.1.1 Написание интерфейсаСоздание CORBA приложения на Java начинается с написания интерфейса для удаленного объекта, используя язык описания интерфейсов (Interface Definition Language, IDL).Создадим файл hello.idl module HelloApp { interface Hello { string sayHello(); oneway void shutdown(); }; }; Данный интерфейс описывает лишь два метода shutdown и sayHello. Причем, нам не важно, что делают эти методы, главное мы определяем, что они есть и определяем какие у них входные и выходные параметры. Далее следует запустить компилятор IDL-to-Java idlj: idlj - fall Hello.idl В текущей директории появилась новая папка HelloApp, в которой содержаться шесть java_файлов. Каждый из них имеет свое назначение. · HelloPOA.java java - абстрактный класс, который представляет собой ни что иное, как скелет сервера (skeleton) и обеспечивает функциональность сервера. · _HelloStub.java - класс, реализующий заглушку (stub) клиента. Обеспечивает функциональность клиента. · HelloHelper.java и HelloHolder.java - классы, предоставляющие вспомогательные функции для CORBA объектов. · HelloOperations.java - класс, содержащий описание интерфейса hello на языке Java. · Hello.java - класс - наследник HelloOperations, поддерживающий интерфейс org.omg.CORBA. Object. 6.1.2 Создание сервераТеперь наша задача - написать класс, реализующий интерфейс hello. В нашем случае это будет HelloImpl. Обратите внимание, на то, что он является наследником класса HelloPOA. В HelloImpl реализованы методы, объявленные в Hello.idl.Для упрощения задачи объявление методов можно взять из файла HelloOperations.java, сгенерированного jdlj.class HelloImpl extends HelloPOA { private ORB orb; public void setORB (ORB orb_val) { orb = orb_val; } // implement sayHello() method public String sayHello() { return «\nHello world!!\n»; } // implement shutdown() method public void shutdown() { orb.shutdown(false); } } Следующим шагом будет создание собственно серверной части приложения. Это будет класс HelloServer. В нем будет всего один метод - стандартная функция main. Первое что мы делаем, создаем ORB. Затем создаем экземпляр класса удаленного объекта (HelloImpl) и регистрируем его в ORB. Дальше вызываем специальную службу имен (NameService) и регистрируем в ней имя удаленного объекта, чтобы клиент смог его найти. Рассмотрим подробнее эти этапы. 1. Создание и инициализация ORB. Производится вызовом статического метода init класса ORB ORB orb = ORB.init (args, null); 2. Создание экземпляра класса удаленного объекта и регистрация его в ORB HelloImpl helloImpl = new HelloImpl(); helloImpl.setORB(orb); 3. Получение контекста имен (NamingContext) org.omg.CORBA. Object objRef = orb.resolve_initial_references («NameService»); NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef); В первой строчке мы получаем объектую ссылку на службу имен (NameService). Но фактически это обыкновенный CORBA_объект и для того, чтобы использовать его как контекст имен (NamingContext), необходимо вызвать метод narrow класса NamingContextHelper, который как бы конкретизирует данный CORBA_объект. 4. Регистрация имени удаленного объекта (HelloImpl) String name = «Hello»; NameComponent path[] = ncRef.to_name(name); ncRef.rebind (path, href); Регистрация имени производится для того, чтобы клиент смог найти удаленный объект. Этой цели служит функция rebind (NameComponent[] nc, Object obj) интерфейса NamingContext. 5. Ожидание запросов от клиента orb.run(); Теперь сервер готов к работе. // HelloServer.java import HelloApp.*; import org.omg. CosNaming.*; import org.omg. CosNaming. NamingContextPackage.*; import org.omg.CORBA.*; import org.omg. PortableServer.*; import org.omg. PortableServer.POA; import java.util. Properties; class HelloImpl extends HelloPOA { private ORB orb; public void setORB (ORB orb_val) { orb = orb_val; } // implement sayHello() method public String sayHello() { return «\nHello world!!\n»; } // implement shutdown() method public void shutdown() { orb.shutdown(false); } } public class HelloServer { public static void main (String args[]) { try { // create and initialize the ORB ORB orb = ORB.init (args, null); // get reference to rootpoa & activate the POAManager POA rootpoa = POAHelper.narrow (orb.resolve_initial_references («RootPOA»)); rootpoa.the_POAManager().activate(); // create servant and register it with the ORB HelloImpl helloImpl = new HelloImpl(); helloImpl.setORB(orb); // get object reference from the servant org.omg.CORBA. Object ref = rootpoa.servant_to_reference(helloImpl); Hello href = HelloHelper.narrow(ref); // get the root naming context // NameService invokes the name service org.omg.CORBA. Object objRef = orb.resolve_initial_references («NameService»); // Use NamingContextExt which is part of the Interoperable // Naming Service (INS) specification. NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef); // bind the Object Reference in Naming String name = «Hello»; NameComponent path[] = ncRef.to_name(name); ncRef.rebind (path, href); System.out.println («HelloServer ready and waiting…»); // wait for invocations from clients orb.run(); } catch (Exception e) { System.err.println («ERROR:» + e); e.printStackTrace (System.out); } System.out.println («HelloServer Exiting…»); } } 6.1.3 Создание клиентаПерейдем к написанию кода для клиента.Основные шаги написания клиентского приложения1. Создание и инициализация ORB2. Получение контекста службы имен (NamingContext)3. Нахождение удаленного объекта4. Вызов метода sayHello.5. Вызов метода shutdown.Как видно, первые два пункта совпадают с этапами создания серверного приложения, поэтому рассматривать их не будем.Третий пункт реализуется тоже достаточно просто. Создается объект NameComponent. Вызывается метод resolve (NameComponent[] path), который отыскивает по имени удаленный объект (стандартный CORBA_объект). При помощи метода narrow (org.omg.CORBA. Object obj) класса helloHelper (сгенерированного idlj компилятором) получаем объектную ссылку на интерфейс hello.String name = «Hello»;helloImpl = HelloHelper.narrow (ncRef.resolve_str(name));Теперь можно вызывать метод sayHello:System.out.println (helloImpl.sayHello());Метод shutdown завершает работы сервера.helloImpl.shutdown(); //testClient.javaimport HelloApp.*;import org.omg. CosNaming.*;import org.omg. CosNaming. NamingContextPackage.*;import org.omg.CORBA.*;public class HelloClient{static Hello helloImpl;public static void main (String args[]){try { // create and initialize the ORBORB orb = ORB.init (args, null); // get the root naming contextorg.omg.CORBA. Object objRef =orb.resolve_initial_references («NameService»); // Use NamingContextExt instead of NamingContext. This is // part of the Interoperable naming Service.NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef); // resolve the Object Reference in NamingString name = «Hello»;helloImpl = HelloHelper.narrow (ncRef.resolve_str(name));System.out.println («Obtained a handle on server object:» + helloImpl);System.out.println (helloImpl.sayHello());helloImpl.shutdown();} catch (Exception e) {System.out.println («ERROR:» + e);e.printStackTrace (System.out);}}}6.1.4 Компиляция и запуск приложенияФайлы HelloServer.java and HelloClient.java, Hello.idl и папка HelloApp, созданная idkj.exe должны храниться в одной папке.Для компиляции клиента и сервера надо в командной строке набратьjavac *.java HelloApp/*.javajavac.exe находится в …\jdk1.5.0\bin.Среда Eclipse не позволяет запускать CORBA_приложения. Для запуска1. Запустить службу orbd - Object Request Broker Daemon (…\jdk1.5.0\bin\orbd.exe). Это делается, чтобы мы смогли получить ссылку на службу имен.start orbd - ORBInitialPort 1050Параметр - ORBInitialPort - номер порта, на котором будет работать сервер имен.2. Запуск сервераstart java HelloServer - ORBInitialPort 1050 - ORBInitialHost localhostУказывается порт, на котором работает сервер имен. Параметр - ORBInitialHost указывает хост, на котором работает сервер имен.3. Запуск клиентаjava HelloClient - ORBInitialPort 1050 - ORBInitialHost localhostУказывается порт, на котором работает сервер имен. Параметр - ORBInitialHost указывает хост, на котором работает сервер имен.Для удобства компиляции и запуска можно создать bat_файл:idlj - fall Hello.idljavac *.java HelloApp/*.javastart java HelloServer - ORBInitialPort 1050 - ORBInitialHost localhostjava HelloClient - ORBInitialPort 1050 - ORBInitialHost localhost6.2 Язык IDLЯзык OMG IDL (Interface Definition Language - Язык Описания Интерфейсов) представляет собой технологически независимый синтаксис для описания интерфейсов объектов. При описании программных архитектур, OMG IDL прекрасно используется в качестве универсальной нотации для определения границ объекта, определяющих его поведение по отношению к другим компонентам информационной системы. OMG IDL позволяет описывать интерфейсы, имеющие различные методы и атрибуты. Язык также поддерживает наследование интерфейсов, что необходимо для повторного использования объектов с возможностью их расширения или конкретизации.IDL является чисто декларативным языком, то есть он не содержит никакой реализации. IDL_спецификации могут быть откомпилированы (отображены) в заголовочные файлы и специальные прототипы серверов, которые могут использоваться непосредственно программистом. То есть IDL_определенные методы могут быть написаны, а затем выполнены, на любом языке, для которого существует отображение из IDL. К таким языкам относятся C, C++, SmallTalk, Pascal, Java, Ada.С помощью IDL можно описать и атрибуты компоненты, и родительские классы которые, она наследует, и вызываемые исключения, и, наконец, методы, определяющие интерфейс, причем с описанием входных и выходных параметров.Структура CORBA IDL файла выглядит следующим образом:module <identifier> { <type declarations>; <constant declarations>; <exception declarations>; interface <identifier> [:<inheritance>] { <type declarations>; <constant declarations>; <attribute declarations>; <exception declarations>; [<op_type>]<identifier>(<parameters>) [raises exception] [context] . . [<op_type>]<identifier>(<parameters>) [raises exception] [context] . . } interface <identifier> [:<inheritance>] . . } Синтаксис языка IDL довольно объемный и не представляется возможным описать его в методическом пособии. Для реализации интерфейса почтового сервера можно дополнить Hello.idl module HelloApp { struct TMessage { string To; string From; string Message; }; typedef sequence<TMessage> TMessages; interface Hello { TMessages GetMessages (in string Name, out short count); oneway void Send (in string Client, in string Name, in string Message); string sayHello(); oneway void shutdown(); }; }; typedef sequence<TMessage> TMessages; - объявление типа динамический массив сообщений TMessage.
|