Интернет-журнал "Домашняя лаборатория", 2007 №6 - Усманов
Шрифт:
Интервал:
Закладка:
В рамках СОМ+ использование DLL суррогата наиболее предпочтительно, так как именно в этом случае сервер сможет использовать все сервисы, предоставляемые СОМ+. Однако, при этом необходимо конфигурировать сервер, определив ряд связанных с ним атрибутов в новой структуре данных — каталоге. Эти вопросы будут рассмотрены позже при изучении СОМ+.
Итак, далее мы рассмотрим размещение сервера PubInProcServer в суррогатном процессе.
Для размещения DLL сервера в суррогатном процессе достаточно сделать несколько дополнительных настроек в реестре, связанных с идентификатором приложения — AppID.
Здесь мы уже приближаемся к идеологии СОМ+. В архитектуре СОМ на верхнем уровне стоит сервер, который может содержать несколько классов, каждый из которых реализует несколько интерфейсов. При этом уникальные идентификаторы (GUID) назначаются только классам, интерфейсам, библиотекам типов, но не серверам. В СОМ+ на верхнем уровне находится приложение, которое может содержать несколько классов (размещенных, конечно, в серверах), которые, в свою очередь, реализуют несколько интерфейсов.
В отличие от сервера, приложение имеет уникальный идентификатор AppID, что позволяет связывать с ним различные атрибуты. С помощью этих атрибутов можно, например, задавать различные ограничения связанные с безопасностью.
В качестве GUID для приложения можно взять GUID одного из классов, входящих в состав приложения. Например, первого класса, описанного в idl-файле.
Для занесения информации о AppID надо в реестре под ключом HKEY_CLASES_ROOT AppID завести новый раздел с GUID данного приложения. В этом разделе можно задавать различные атрибуты, управляющие доступом к приложению и т. д. Мы здесь зададим параметр с именем DllSurrogate и с пустым значением. Это означает, что приложение с данным AppID должно выполняться в стандартном суррогатном процессе (dllhost. ехе).
Теперь надо связать все входящие в приложение классы с данным AppID. Для этого под ключом HKEY_CLASES_ROOT CLSID clsid_данного_класса надо завести дополнительный строковый параметр AppID со значением равным AppID нашего приложения. Это надо повторить для всех классов нашего приложения.
Клиент PubCiient был жестко ориентирован на работу с сервером в процессе клиента. Эта ориентация задавалась при активации фабрики класса. Например,
hr = CoGetClassObject(CLSID_CoBook, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void**)&pBF);
Параметр CLSCTX_INPROC_SERVER задает использование именно сервера в процессе клиента.
Для загрузки сервера в суррогатный процесс достаточно заменить этот параметр на CLSCTX_LOCAL_SERVER для обоих задействованных в приложении классов: CoBook и СоJournal.
Итак, сервер будет загружаться в DLL суррогат. Выполняется это следующим образом. При построении фабрики класса (CoGetClassObject) система обнаруживает, что клиент требует локальный сервер. Однако в реестре для данного класса имеется только путь к DLL, реализующей сервер в процессе клиента — параметр InProcServer32. Однако, для данного класса имеется и параметр AppID, задающий GUID приложения, использующего данный класс. Обращаясь к разделу реестра, описывающего данное приложение, система обнаруживает, что требуется загрузка сервера в суррогатный процесс — параметр DllSurrogate.
Стандартный маршалинг
Итак, клиент будет размещен в одном процессе, а сервер в другом. Как же будут осуществляться вызовы методов, передача параметров, возвращение результатов? Очевидно, что здесь не работают механизмы, использовавшиеся ранее, когда клиент и сервер находились в одном адресном пространстве.
Идеология различных распределенных архитектур основана на использовании понятий прокси, менеджера прокси, канала и заглушки.
В СОМ прокси является объектом, который агрегирован в еще один объект — менеджер прокси. Менеджер прокси загружен в адресное пространство клиента и имитирует для него удаленный объект. Точнее, каждый используемый данным клиентом интерфейс удаленного объекта имитируется своим прокси и все эти прокси агрегированы менеджером прокси. Таким образом, клиент может напрямую вызывать методы удаленного объекта как и в случае сервера в пространстве клиента. Конечно, реализация методов удаленного объекта не полная. Реально прокси принимает вызов клиента, кодирует и пакетирует его и передает специальному объекту канала, который ответственен за физическую передачу данных по сети. На стороне сервера пакеты принимает заглушка, в чьи функции входит распаковка вызова и передача его серверу. Таким образом, и для сервера создается иллюзия того, что клиент находится в одном с ним адресном пространстве.
Процесс упаковки, передачи и распаковки при вызове метода удаленного объекта и называется маршалингом. В СОМ имеется три типа маршалинга:
• Пользовательский маршалинг
Это наиболее сложный для реализации выбор, но при этом программист получает полный контроль над процессом передачи данных. Дня реализации пользовательского маршалинга надо реализовать станартный интерфейс iMarshai, выбрать и реализовать протокол передачи данных.
• Стандартный маршалинг
Здесь используются прокси и заглушки, взаимодействующие друг с другом по протоколу ORPC (Object RPC). Причем, если для описания интерфейсов используется IDL, от программиста не требуется писать какой-либо код. Компилятор с IDL — Microsoft IDL (MIDL) генерирует несколько файлов с кодами прокси и заглушки. Используя их можно построить DLL, которая после регистрации и обеспечит маршалинг для описанных в IDL-файле интерфейсов.
• Универсальный маршалинг
В этом случае не нужно даже строить DLL заглушки/прокси. Эта DLL строится "на лету". Необходимые условия:
♦ в методах интерфейсов используются параметры только так называемых variant-совместимых типов (некоторое подмножество типов, допустимых в IDL);
♦ в IDL файле интерфейсы описаны с атрибутом oleautomation;
♦ имеется зарегистрированная библиотека типов, в которой описаны интерфейсы;
♦ информация об интерфейсах включена в реестр под ключом НКЕY_CLASSЕS_ROOT Interface.
Возможность универсального маршалинга связана с тем, что для всех стандартных интерфейсов код маршалинга уже существует. При использовании упомянутого ограниченного набора типов этот код может использоваться для автоматического формирования кода маршалинга нового интерфейса.
Далее приведен стандартный алгоритм действий для построения DLL прокси/заглушки, обеспечивающих стандартный маршалинг:
1. Открыть новый проект Win32 DLL — PSPubinProcServer и добавить в него сгенерированные компилятором с IDL файлы:
♦ PubInPrосServerTуреInfo_i.с — определения GUID, упомянутых в IDL-файле,
♦ PubInPrосServerTуреInfo_р. с, dlldata.c — код для прокси/заглушек и макросы для саморегистрации формируемой DLL.
2. Создать DEF-файл PSPubinProcServer.def
3. LIBRARY PSPubInProcServer.dll
4. EXPOTRS
5. DllGetClassObject @1 PRIVATE
6. DllCcanUnioadNow @2 PRIVATE
7. DllRegisterServer @3 PRIVATE
8. DllUnregisterServer @4 PRIVATE
9. В диалоге Project]Settings на вкладке C/C++ в поле Preprocessor definitions добавить через запятую флажки REGISTER_PROXY_DLL и _WIN32_DCOM. В результате в проект будет вставлен код саморегистрации.
10. В том же диалоге на вкладке Link в поле Object/library moduls добавить через пробел ссылки на библиотеки поддержки удаленного вызова процедур rpcndr.lib, rpcns4.lib, rpcrt4.lib.
11. Откомпилировать проект и зарегистрировать построенную DLL прокси/заглушки с помощью Tools|Register Control.
В процессе саморегистрации построенной DLL прокси/заглушки