Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Брокеры объектных запросов (ORB)






 

ORB-брокер действует от имени программы. Он посылает сообщения удаленному объекту и возвращает сообщения от него. Поведение ORB-брокера можно сравнить с посредником между локальными и удаленными объектами. ORB-брокер решает все вопросы, связанные с маршрутизацией запроса от программы к удаленному объекту и с маршрутизацией ответа программе, принятого от удаленного объекта. Такое посредничество делает коммуникации между системами практически прозрачными. ORB-брокер избавляет программиста от необходимости программирования сокетов между процессами, выполняющимися на различных компьютерах. И точно так же он устраняет необходимость в программировании каналов и очередей с FIFO-дисциплиной между процессами, выполняющимися на одном компьютере. Он берет на себя немалый объем сетевого программирования, без которого не обойтись при создании распределенных программ. Более того, он стирает различия между операционными системами, языками программирования и аппаратными средствами. При программировании локальных объектов программисту больше не нужно беспокоиться о том, на каком языке реализованы удаленные объекты, на какой платформе они выполняются и к какой сети они «приписаны»: Internet или локальной intranet. ORB-брокер использует IOR-ссылки, чтобы упростить взаимодействие между компьютерами, сетями и объектами. Обратите внимание на то, что IOR-ссылка (см. рис. 8.2) содержит информацию, которая может быть использована для TCP/IP-соединений. Мы представили лишь частичное описание IOR-компонентов, поскольку IOR-дескриптор должен быть «черным ящиком» для разработчика. ORB-брокер использует IOR-ссылки, чтобы найти объект назначения. Обнаружив объект, ORB-брокер активизирует его и передает аргументы, необходимые для вызова этого объекта. ORB-брокер ожидает завершения обслуживания запроса и возвращает вызывающему объекгу ожидаемую информацию или исключение, если вызов метода оказался неудачным. Упрощенная последовательность действий, выполняемых ORB-брокером от имени локального объекта, показана на рис. 8.3.

Действия, перечисленные на рис. 8.3, представляютупро щ енную схему того, что делает ORB-брокер, взаимодействуя с удаленным объектом. Эти действия практически незаметны для локального объекта. Локальный объект вызывает один из методов удаленного объекта, а ORB-брокер делает «свою работу» от имени локального объекта. ORB-брокер выполняет большой объем обработки, заключенный всего лишь в нескольких строках кода. Обычно распределенное объектно-ориенти-рованное приложение состоит по крайней мере из двух программ. Каждая программа имеет один или несколько объектов, которые взаимодействуют друг с другом, «пересекая» адресные пространства. Характер взаимодействия объектов определяется отношениями «клиент-сервер», «изготовитель-потребитель» или базируется на принципе равноправия (модель равноправных узлов). Следовательно, если у нас есть две программы, то одна будет действовать как клиент, а другая — как сервер, или одна — как изготовитель, а другая — как потребитель, либо обе они будут равноправными. В программе 8.1 реализован потребитель, который вызывает простой удаленный объект калькулятора. На примере этой программы демонстрируется, как можно получить доступ к удаленному объекгу, а также как инициализируется и используется ORB-брокер.

УПРОЩЕННАЯ ПОСЛЕДОВАТЕЛЬНОСТЬ ДЕЙСТВИЙ ORB-БРОКЕРА ПРИ ВЫЗОВЕ МЕТОДА УДАЛЕННОГО ОБЪЕКТА _

1. Найти удаленный объект. _

2. Активизировать модуль, содержа щ ий искомый объект, если таковой е щ е не активизирован. _

3. Передать аргументы удаленному объекту. _

4. Ожидать ответа после вызова метода удаленного объекта. _

5. Вернугьлокальномуобъекту информацию или исключение, если вызовудаленного метода оказался неуспешным. _

Рис. 8.3. Упрощенная последовательность действий, выполняемых ORB-брокером от имени локального объекта

 

// Программа 8.1

1 using namespace std;

2 #include «adding_machine_impl.h»

3 #include < iostream>

4 #include < fstream>

5 #include < string> 6

8 int main(int argc, char *argv[])

9 {

10 CORBA:: ORB_var Orb = CORBA:: ORB_init(argc, argv, «mico-local-orb»);

11 CORBA:: BOA_var Boa = Orb-> BOA_init(argc, argv, «mico-local-boa»);

12 ifstream In(«adding_machine.objid»);

13 string Ref;

14 if('In.eof()){

15 In» Ref;

16 }

17 In.close();

18 CORBA:: Object_var Obj = Orb-> string_to_object(Ref.data());

19 adding_machine_var Machine =adding_machine:: _narrow(Obj);

20 Machine-> add(700);

21 Machine-> subtract(250);

22 cout < < «Результат равен " «Machine-> result()«endl;

23 return(0);

24 }

При выполнении строки 10 ORB-брокер инициализируетс я. Строка 15 обеспечивает считывание из файла IOR-ссылки на объект adding_machine. Одно из прекрасных свойств IOR-ссылки состоит в том, что ее можно хранить как простую строку и передавать другим программам. Передачу IOR-ссылки проще всего реализовать с помощью аргументов командной строки, переменных среды или файлов. IOR-ссылку можно отправить по электронной почте или с помощью протокола передачи файлов (File Transfer Protocol — FTP). IOR-ссылки совместно используют файловые системы, и их можно загружать с Web-страниц. Если некоторая программа имеет IOR-ссылку на удаленный объект, то для доступа к нему можно использовать ORB-брокер. Другие методы связи между объектами с помощью IOR-ссылок будут рассмотрены ниже в этой главе. Но для начала вполне достаточно использования файловых систем. Итак, в программе 8.1 IOR-ссылка была получена путем преобразования объектной ссылки в «строковую» форму (с использованием ORB-брокера удаленного калькулятора) и записана в файл. При выполнении строки 18 локальный объект Orb преобразует «строковую» IOR-ссылку обратно в объектную. В строке 19 эта объектнал ссылка используется для реализации объекта adding_machine. Обратите внимание на то, что при вызове методов этого объекта adding_machine выполняется соответствующий код удаленного калькулятора (см. строки 20, 21 и 22).

Machine-> add(700);

Machine-> subtract(250);

cout ««Результат равен " «Machine-> result() «endl;

И хотя вызовы этих методов сделаны в нашей локальной области види м ости, они относятся к выполняемому колу в другом адресном пространстве (в данном случае — даже к другому компьютеру). Для разработчика местоположение объекта Machine как будто перестает иметь значение. После создания (в строке 19) этот объект используется как любой другой объект С++. И хотя существуют весьма значительные различия между вызовами локальных и удаленных объектов [15], объектно-ориентированное представление, тем не менее, поддерживается, и с точки зрения объектно-ориентированного программирования удаленные объекты ведут себя как локальные. Код, представленный в программе 8.1, является кодом клиентской части приложения (или кодом «потребителя»), поскольку в нем используются возможности объекта adding_machine. Поэтому теперь (для получения завершенного приложения калькулятора) нам нужен код «ответной части», который реализует объект adding_machine. Код этого второго компонента представлен в программе 8.2.

// Программа 8.2

1 #include < iostream>

2 #include < fstream>

3 #include «adding_machine_impl.h» 4

5 6 7

8 int main(int argc, char *argv[])

9 {

10 CORBA:: ORB_var Orb = CORBA:: ORB_init(argc, argv, «mico-local-orb»);

11 CORBA:: BOA_var Boa = Orb-> BOA_init(argc, argv, «mico-local-boa»);

12 adding_machine_impl *AddingMachine =new adding_machine_impl;

13 CORBA:: String_var Ref = Orb-> object_to_string(AddingMachine);

14 ofstream Out(«adding_machine.objid»);

15 Out «Ref «endl;

16 Out.close();

17 Boa-> impl_is_ready (CORBA:: ImplementationDef:: _nil ());

18 Orb-> run();

19 CORBA:: release(AddingMachine);

20 return(0);

21 } 22 23

Обратите внимание на то, что программа-«изготовитель» также должна инициализировать объект Orb (в строке 10). Это — одно из важных требований, предъявляемых к CORBA-ориентированным программам, поскольку каждая программа реализует взаимодействие с удаленными объектами с помощью ORB-брoкepa. Именно поэтому инициализация ORB-объекта— первое действие, которое должна выполнить CORBA-программа. В строке 12 объявляется реальный объект adding_machine. Это именно тот объект, с которым в действительности связывается программа 8.1. В строке 13 объектная ссылка на реальный объект adding_machine преобразуется в «строковую» форму, а затем записывается в обычный текстовый файл, чтобы ее можно было без труда прочитать. После того как IOR-ссылка записана в файл, объект Orb ожидает запроса. При каждом вызове одного из его методов этот объект выполняет соответствующее арифметическое действие (сложение или вычитание). Значение результата передается посредством вызова метода result() объекта adding_machine. Программы 8.1 и 8.2 демонстрируют базовую структуру, которую должны иметь CORBA-программы. Код, создающий объект adding_machine, начинается с объявления его CORBA-класса. Каждый CORBA-объект начинается как IDL-проект (Interface Definition Language — язык описания интерфейсов).

 

Язык описания интерфейсов (IDL): более «пристальный» взгляд на CORBA-объекты

 

Язык описания интерфейсов (IDL) — стандартный язык объектно-ориентированного проектирования, который используется для разработки классов, предназначенных для распределенного программирования. Он применяется для отображения интерфейса класса и отношений между классами, а также для определения прототипов функций-членов, типов параметров и типов значений, возвращаемых функциями. Одно из основных назначений языка IDL — отделить интерфейс класса от его реализации. Но дл я определени я самих функций-членов и членов данных IDL не используетс я. Язык IDL определ я ет только интерфейс функции. Основные ключевые слова IDL перечислены в табл. 8.1.

 

Таблица8.1. Ключевые слова IDL    
abstract enum native struct
any factory Object supports
attribute FALSE octet typedef
boolean fixed oneway unsigned
case float out union
char in raises ValueBase
const inout readonly valuetype
cell interface sequence void
double long short wchar
exception module string  

Ключевые слова, перечисленные в табл. 8.1, представл я ют собой зарезервированные слова, используемые в CORBA-программах. Помимо определени я интерфейса функций дл я класса, я зык IDL используетс я дл я определени я отношений между к л ассами. IDL под д ерживает:

• типы, определенные пользователем;

• последовательности, определенные пользователе м;

• типы массивов;

• рекурсивные типы;

• семантику исключений;

• модули (по аналогии с пространствами имен);

• единичное и множественное наследование;

• поразрядные арифметические операторы.

Приведем IDL-определение для класса adding_machine из листинга 8.2:

interface adding_machine{

void add(in unsigned long X);

void subtract(in unsigned long X);

long result();

}

Это определение начинается с ключевого слова CORBA interface. Обратите внимание на то, что данное объявление интерфейса класса adding_machine не включает ни одной переменной, которая бы могла хранить результат выполнения операций сложения и вычитания. Методы add () и subtract () принимают в качестве параметра одно значение типа unsigned long. Объявление типа параметра сопровождается ключевым словом CORBA in, который говорит о том, что данный параметр является входным (mput). Это объявление класса хранится в отдельном исходном файле adding_machine.idl. Исходные файлы, содержащие ГОЬюпределения, должны иметь. idl-расширения. Прежде чем такой файл можно будет использовать, его необходимо преобразовать к С++чЈюрмату. Это преобразование можно выполнить с помощью препроцессора или отдельной программы. Все CORBA-реализации включают IDL-компиляторы. Существуют IDL-компиляторы лля языков С, Smalltalk, С++, Java и др. IDL-компилятор преобразует ГОЬюпределения в код соответствующего языка. В данном случае IDL-компилятор преобразует объявление интерфейса в легитимный C++-код. В зависимости от конкретной CORBA-реализации IDL-компилятор вызывается с использованием синтаксиса, который будет подобен слелующему:

idl adding_machine.idl

При выполнении этой команды создается файл, содержащий С++-код. Поскольку наше IDL-определение хранится в файле adding_machine. idl, MICO IDL-компилятор создаст файл adding_machine. h, который будет содержать несколько каркасных C++-классов и CORBA-типов данных. Базовые IDL-типы данных приведены в табл. 8.2.

 

Таблица 8.2. Базовые IDL ипы дан н ых

IDL-типы данных

Диапазон

Размер

long

>

 

_2»-2' 5 -

> 16 бит

 

0-2 v - 1

> 32 бит

 

IDL-типы данных Диапазон Размер
long -231 - 231-1 & #8805; 32 бит
short -215 - 215-1 & #8805; 16 бит
unsigned long 0 - 232-1 & #8805; 32 бит
unsigned short 0-216-1 & #8805; 16 бит
float IEEE с обычной точностью & #8805; 32 бит
double IEEE с двойной точностью & #8805; 64 бит
char ISO л атинский-1 & #8805; 8 бит
string ISO л атинский-1, за иск л ючением ASCII NULL Переменный
boolean TRUE ИЛИ FALSE Не определен
octet 0-255 & #8805; 8 бит
any Произвольный тип, идентифицируемый динамически ПеременныйПеременный

Даже после того как IDL-компилятор создаст из определения интерфейса С++-код, реализация методов интерфейсного класса остается все еще неопределенной. IDL-компилятор создает несколько С++-конструкций, которые предназначены для использования в качестве базовых классов. В листинге 8.3 показано два класса, сгенерированных MICO IDL-компилятором на основе файла adding_machine.idl.

// Листинг 8.3. Два класса, сгенерированные

// MICO IDL-компилятором из файла

// adding_machine.idl

class adding_machine: virtual public CORBA:: Object{

public:

virtual ~adding_machine();

#ifdef HAVE_TYPEDEF_OVERLOAD

typedef adding_machine_ptr _ptr_type;

typedef adding_machine_var _var_type;

#endif

static adding_machine_ptr _narrow(CORBA:: Object_ptr obj);

static adding_machine_ptr _narrow(CORBA:: AbstractBase_ptr obj);

static adding_machine_ptr _duplicate(adding_machine_ptr _obj){

CORBA:: Object:: _duplicate (_obj); return _obj;

}

static adding_machine_ptr _nil(){

return 0;

}

virtual void *_narrow_helper(const char *repoid);

static vector< CORBA:: Narrow_proto> *_narrow_helpers;

static bool _narrow_helper2(CORBA:: Object_ptr obj);

virtual void add(CORBA:: ULong X) = 0;

virtual void subtract(CORBA:: ULong X) = 0;

virtual CORBA:: Long result() = 0;

protected:

adding_machine(){};

private:

adding_machine(const adding_machine&);

void operator=(const adding_machine&);

};

class adding_machine_stub: virtual public adding_machine{

public:

virtual ~adding_machine_stub();

void add(CORBA:: ULong X);

void subtract(CORBA:: ULong X); CORBA:: Long result();

private:

void operator=(const adding_machine_stub&);

};

Файл adding_machine.idl — это входные данные для компилятора, а файл adding_machine.h вместе с каркасны м и класса м и— результат его работы. Чтобы реализовать интерфейсы функций, объявленные в исходно м IDL-файле, разработчик использует наследование. Напри м ер, в листинге 8.4 представлен определенный пользователе м класс, который обеспечивает реализацию для одного из каркасных классов, созданных IDL-ко м пиляторо м.

// Листинг 8.4. Класс реализации структурных классов, // созданных IDL-компилятором

class adding_machine_impl: virtual public adding_machine_skel {

private:

CORBA:: Long Result;

public:

adding_machine_impl (void){

Result = 0;

};

void add(CORBA:: ULong X){

Result = Result + X;

};

 

void subtract(CORBA:: ULong X){

Result = Result - X;

};

CORBA:: Long result(void){

return(Result);

};

Один из каркасных файлов, созданных IDL-ко м пилятором из интерфейсного клас са adding_machine, называется adding_machine_skel. Обратите внимание на то, что при выведении новых классов IDL-компилятор берет имя из определения интерфейса. Наш класс adding_machine_impl обеспечивает реализацию интерфейса функций, объявленного с использованием языка IDL. Во-первых, в классе adding_machine_impl объявляется член данных Result. Во-вторых, здесь предлагается реализация методов add(), subtract () и result (). В то время как интерфейсный класс adding_machine включает объявление этих методов, класс adding_machine_impl обеспечивает их реализацию. Определяемый пользователем класс adding_machine_impl должен наследовать из базового класса множество функций, полезных для распределенного программирования. В этом и состоит основная схема работы, связанной с CORBA-программированием. Интерфейсный класс предназначен для представления используемых интерфейсов. Назначение IDL-компилятора ~ сгенерировать реальные каркасные С++-классы, исходя из определения интерфейса. Разработчик выводит класс из одного каркасных и обеспечивает реализацию методов, определенных в интерфейсном классе, и членов данных, которые должны использоваться для хранения атрибутов объекта. Итак, создание реальных С++-классов из IDL-определения представляет собой процесс, состоящий из трех действий.

1. Проектирование интерфейсов классов, отношений и иерархии с использование м языка IDL.

2. Использование IDL-ко м пилятора д ля генерирования реальных каркасных C++-классов на основе IDL-классов.

3. Использование наследования для создания пото м ков из одного из нескольких каркасных классов и реализация м етодов интерфейса, унаследованных от каркасных классов.

Мы рассмотрим этот процесс более детально ниже в этой главе. Но сначала познакомимся с базовой структурой программы потребителя.

 

 






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.