Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
os7.doc
Скачиваний:
0
Добавлен:
20.06.2023
Размер:
217.09 Кб
Скачать

2. Именованные каналы Windows

Именованные каналы предоставляют приложениям надежную двухстороннюю связь.

Именованный канал создается вызовом:

NP = CreateNamedPipe("\\\\.\\pipe\\mypipe",

PIPE_ACCESS_DUPLEX,

PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_WAIT,

1,

0,

0,

INFINITE,

NULL);

Приложение, создавшее такой канал, становится сервером.

Сервер переходит в режим ожидания запросов клиента с помощью вызова:

ConnectNamedPipe(NP, NULL);

Поскольку вызов функции ConnectNamedPipe() приводит к ожиданию процесса, то лучше ее вызывать в отдельном потоке.

Клиент подключается к каналу с помощью вызова:

NP = CreateFile("\\\\pc_name\\pipe\\mypipe",

GENERIC_READ|GENERIC_WRITE,

0,

NULL,

OPEN_EXISTING,

FILE_ATTRIBUTE_NORMAL,

NULL);

После того, как соединение между сервером и клиентом будет установлено, они могут обмениваться данными с помощью вызовов ReadFile() и WriteFile(), аналогично предыдущему случаю.

Аналогичным же образом (CloseHandle()) канал закрывается.

3. Удаленные вызовы процедур - rpc

Вспомним опять традиционную модель процедурного программирования. Прикладная программа выглядит как последовательность вызовов процедур, следующим образом:

{

...

Call1();

Call2();

...

}

Удаленные вызовы процедур – это средство расширения традиционной модели программирования на распределенные системы.

Хотя и можно использовать RPC сами по себе, чаще они все-таки являются средством реализации COM и DCOM.

Понятия интерфейса и глобально уникальных идентификаторов являются фундаментальными для RPC, COM и DCOM.

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

Процедурный интерфейс скрывает все эти действия.

Базовым недостатком RPC является синхронность. Т. е. когда клиент обращается с RPC-запросами к процедуре сервера, то он блокируется до момента, пока сервер не выполнит функцию и не возвратит результаты.

Существуют усовершенствованные RPC, обеспечивающие асинхронные вызовы. В них для оповещения клиента о выполнении RPC используются обратные вызовы. Хотя структура синхронной программы существенно проще асинхронной.

Программа, реализующая технологию клиент/сервер с помощью RPC, будет выглядеть следующим образом:

{

...

CSInterface(Call1);

CSInterface(Call2);

...

}

Процедура CSInterface() - интерфейсная процедура, первый аргумент которой - это, обычно, имя серверной процедуры, которую необходимо выполнить. Могут передаваться и дополнительные параметры в процедуру CSInterface().

Структура удаленного вызова процедуры может выглядеть следующим образом:

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

void CSInterface(Procedure P)

{

switch P {

case Call1: {

Создание структур данных для передачи по сети;

Посылка запроса на сервер;

Выполнение процедуры Call1 на сервере;

Подготовка ответа;

Посылка ответа клиенту;

Прием ответа;

}

case Call2: {

...

}

}

}

Синхронный характер процедурного интерфейса иллюстрируется следующим рисунком:

Клиент Сервер

------------------- -------------------

| | | |

|1. ServerRequest | -----> 2. ------> |-----> 3. |

| (приостанов | | . |

| выполнения) | | . |

| 6.<-----| <----- 5. <------ |4. RespondClient;|

| . | | |

| . | | |

------------------- -------------------

Цифры показывают порядок происходящих событий:

  1. Запрос;

  1. Передача запроса;

  1. Начало обработки запроса;

  1. Ответ;

  1. Посылка ответа;

  1. Получение результата клиентом.

Реализация без ожидания иллюстрируется следующим образом:

Клиент Сервер

------------------- -------------------

| | | |

|1. ServerRequest | -----> 2. ------> |-----> 3. |

| . | | . |

| . | | . |

| 6.<-----| <----- 5. <------ |4. RespondClient;|

| . | | |

| . | | |

------------------- -------------------

Клиент дает запрос серверу и асинхронно продолжает работать одновременно с серверным приложением. Позднее клиент либо запрашивает сервер, либо получает уведомление через специальное средство процедуру обратного вызова.

Структура программы клиента с процедурой обратного вызова включает в себя следующие элементы:

1) Описание процедуры обратного вызова. Содержание процедуры обратного вызова полностью определяется характером задач уровнем протокола. На сетевом уровне (3) - это может быть простая установка флага, извещающего клиента о завершении операции. На уровне презентации (6), например, в протоколе DDE, - это достаточно сложные действия.

void CallbackProc()

{

...

}

2) Предусматривается передача адреса процедуры CallbackProc обратного вызова интерфейсной процедуре CSInterface. Если в качестве фактического параметра передается NULL, то выполнение процедуры CSInterface происходит синхронно, а если передается не NULL, а адрес CallbackProc, то выполнение происходит асинхронно.

Т.е. по выполнению запроса коммуникационная среда сама вызывает процедуру CallbackProc, и тем самым оповещает клиента о выполнении запроса.

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

Создание RPC начинается с описания интерфейса, экспортируемого сервером.

Интерфейс создается на языке описания интерфейсов IDL (Interface Definition Language).

Язык описания интерфейса имеет строго определенные правила. Например:

  1. Все функции имеют тип void;

  1. Параметры сопровождаются модификаторами [in], [out] (входной, выходной);

  1. Типы данных стандартные (int, long). ANSI

Интерфейс содержит глобальный уникальный идентификатор (GUID). С его использованием RPC регистрируется в системе. На основе регистрации идет поиск машины, на которой RPC выполняется, при вызове RPC процессом-клиентом.

GUID создается специальной программой, например, uuidgen.

Пример результата работы этой программы

96fa7b8c-92f7-430b-b552-bdb73188c853

Пример интерфейса:

[ uuid (96fa7b8c-92f7-430b-b552-bdb73188c853),

version (1.0),

pointer_default (unique) ]

interface AboutRemoteSystem

{

void get_disk_free_space([in, string, size_is (256)] char* RootPathName,

[out] long* SecPerClus,

[out] long* BytesPerSec,

[out] long* NumFreeClus);

}

Текст интерфейса обрабатывается специальным компилятором, в результате чего формируются так называемые суррогаты (stubs) клиента и сервера.

Если, например, файл интерфейса имеет имя syscommands.idl, то компилятор сформирует файлы:

  1. syscommands.h;

  1. syscommands_s.c – суррогат сервера;

  1. syscommands_c.c – суррогат клиента.

Файлы syscommands.h, syscommands_s.c необходимо включить в проект сервера, а файлы syscommands.h, syscommands_c.c необходимо включить в проект клиента.

Суррогат клиента выполняет следующие действия:

  1. Преобразует параметры в вид, пригодный для передачи по каналу;

  1. Устанавливает соединение с сервером;

  1. Передает серверу данные;

  1. Ждет ответа от сервера;

  1. Получает данные;

  1. Преобразует данные в вид, пригодный клиенту;

  1. Передает данные клиенту.

Суррогат сервера выполняет следующие действия:

  1. Ждет запросы от клиентов;

  1. Получив запрос, преобразует принятые данные в вид, пригодный для выполнения процедуры;

  1. Выполняет процедуру;

  1. Готовит данные-результаты к передаче по каналу;

  1. Передает данные по каналу.

Внешне программа клиента, вызывающего удаленную процедуру, очень похожа на программу, вызывающую локальную процедуру.

Фрагмент клиента представлен ниже:

char Drive[] = "C:\\";

int SecPerClus, BytesPerSec, NumFreeClus;

get_disk_free_space (Drive, &SecPerClus, &BytesPerSec, &NumFreeClus);

Программа сервер существенно сложнее реализуется, чем программа-клиент.

Этапы инициализации сервера следующие:

  1. Регистрирует в библиотеке RPC коммуникационный протокол, который будет поддерживать сервер (TCP/IP или именованные каналы):

RpcServerUseProtseqEp();

  1. Регистрирует в библиотеке RPC интерфейс, который поддерживает сервер:

RpcServerRegisterIf();

  1. Получает набор ссылок, через которые сервер будет взаимодействовать с библиотекой RPC:

RpcServerInqBindings(&pBindVector);

  1. Через полученные ссылки публикует свои возможности в специальной базе данных “RPC name service database”. Клиент запрашивает специальный сервис “RPC name service” при поиске сервера, способного выполнить запрос.

RpcNsBindingExport();

  1. Переходит в состояние ожидания запросов:

RpcServerListen();

Непосредственное соединение обеспечивают специальные библиотеки. При этом возможна передача как по протоколам TCP/IP, так и через именованные каналы (Windows).

Соседние файлы в предмете Операционные системы