Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Гл.11 ОС буклет.doc
Скачиваний:
10
Добавлен:
11.11.2018
Размер:
357.38 Кб
Скачать

11.2.3. Использование Microsoft rpc

Разработка приложений с использованием Microsoft RPC основывается на тех же принципах, что и Sun RPC, но имеет некоторые особенности.

В первую очередь эта технология может использовать разные базовые средства связи (в частности TCP/IP и поіменовані каналы). Кроме того, возможна разработка клиентского приложения без явного задання соединения с сервером.

Разработка IDL-файла

Разработку приложения начинают с описания его интерфейсов на IDL.

Каждому интерфейсу ставят в соответствие универсальный уникальный идентификатор (UUID) -128-бітне число, генерирующее с помощью специального алгоритма, который обеспечивает высокую степень уникальности.

За этим идентификатором RPC-клиенты идентифицируют интерфейсы, экспортированные серверами.

Для создания UUID используют утилиту uuidgen.

Каждый интерфейс сопровождают атрибуты, перечисленные в квадратных дужках перед ключевым словом и interface:

  • uuid — UUID для этого интерфейса;

  • version — версия интерфейса;

  • auto_handle — значит, что клиентское применение не должно явно задавать код для установления соединения с сервером - это будет сделано из кода заглушки (есть и другие способы организации связи, например, при наличии атрибута implicitjiandle связь должна быть установлена явно).

Каждый параметр интерфейса тоже сопровождают атрибуты:

  • in, out - режим параметра (in - входной, out - выходной);

  • string — параметр нужно рассматривать как строка символов.

Приведем пример IDL-файла, который задает один интерфейс с одной процедурой. Дальше будем считать, что он называется mугрс. idl.

[uuid(c0579cff-e76a-417d-878b-1195d366385). version(l.O), auto_handle]

interface thello { /* определение интерфейса ihello */

void say_msg([in.string] unsigned char* msg);

}

IDL-файл обрабатывают IDL-компилятором (midl):

midl.exe /app_config myrpc.idl

Параметр /app_config задают в случае, когда в IDL-файле присутствуют атрибуты, которые касаются всего применения (в нашем случае это autojiandl e). Если его не указать, такие атрибуты задаются в отдельном файле с расширением .acf.

В результате обработки IDL-файла создадутся файлы заглушек для клиента и сервера (myrpc_c.c i myrpc_s.c), которые нужно скомпоновать в соответствующие выполняемые файлы, а также заглавный файл myrpc.h, что должен быть подключен в исходные файлы клиента и сервера.

Разработка отдаленных процедур

Отдаленные процедуры имеют такой вид, как и обычные. Отметим, что типы данных IDL отвечают типам языка С (а не типам Win32 АРI, таким как DWORD).

void say_msg(unsigned char* msg) { // код отдаленной процедуры

printf('от клиента: %s\n". msg);

}

Разработка сервера

В коде сервера в первую очередь нужно указать библиотеке поддержки RPC, какой протокол собирается использовать сервер и как идентифицировать сервер в соответствии с этим протоколом (какая его конечная точка - endpoint).

RPC_STATUS RPC_ENTRY RpcServerUseProtseqEp(unsigned char *prot.

unsigned int max_calls, unsigned char *endpoint, void *sec_desc);

где: prot - строка, которая определяет протокол ("ncacn_ip_tcp" - TCP/IP, "ncacn_np" -поіменовані каналы);

max_calls — максимальное количество соединений с сервером (значения по умолчанию задают как RPC_C_LISTEN_MAX_CALLS_DEFAULT);

endpoi nt — строка, которая определяет конечную точку (для TCP/IP он задает порт, для поименованных каналов — имя канала).

Эта функция возвращает статус RPC-вызова; если он равняется 0 (RPCS0K) — вызов завершился успешно. Аналогичный код возвращают и другие RPC-функции.

// сервер использует TCP/IP. прослушивает порт 5000

RpcServerUseProtseqEp("ncacn_ip_tcp". 5. "5000", NULL);

После задання протокола необходимо зарегистрировать интерфейсы в библиотеке поддержки RPC для того, чтобы клиенты могли его находить:

// для каждого интерфейса из IDL-файла

RpcServerRegisterIf(ihello_v1_0_s_ifspec. NULL. NULL);

Первым параметром задают структуру определения интерфейса, которую генерирует rnidl.

Имя такой структуры строят на основании имени интерфейса и его версии: имя_v1_0_s_іfspec.

Теперь клиенты смогут найти сервер, и можно перейти в режим ожидания соединений:

// ожидание соединений от клиентов

RpcServerListen(1, 5. FALSE);

Перед завершением работы сервер должен упразднить регистрацию своих интерфейсов в библиотеке поддержки

RpcServerUnregisterlf(NULL. NULL. FALSE);

Разработка клиента

Как отмечалось, в случае использования в IDL-файле атрибута auto_handl e в коде клиента не нужно явно задавать соединения с сервером. В этом случае код RPC-клиента может вообще не отличаться от кода применения, которое вызывает локальные процедуры. Но поскольку RPC-клиент обращается к отдаленным серверам, ошибки, которые могут возникать, должны обрабатываться особенным образом. Для организации обработки ошибок есть набор специальных макросов, которые реализуют обработку исключительных ситуаций в стиле языка C++: RpcTryExcept задает блок для проверки, RpcExcept - обработчик исключительной ситуации, RpcEndExcept завершает код обработки. Для определения кода ошибки в теле обработчика используют функцию RpcExceptionCodeO.

RpcTryExcept {

say_msg("he"l"lo"); // вызов отдаленной процедуры

}

RpcExcept(1) {

ргintf("ошибка RPC-вызова с кодом %d\п". RpcExceptionCode());

}

RpcEndExcept;