Навигация
Главная
Поиск
Форум
FAQ's
Ссылки
Карта сайта
Чат программистов

Статьи
-Delphi
-C/C++
-Turbo Pascal
-Assembler
-Java/JS
-PHP
-Perl
-DHTML
-Prolog
-GPSS
-Сайтостроительство
-CMS: PHP Fusion
-Инвестирование

Файлы
-Для программистов
-Компонеты для Delphi
-Исходники на Delphi
-Исходники на C/C++
-Книги по Delphi
-Книги по С/С++
-Книги по JAVA/JS
-Книги по Basic/VB/.NET
-Книги по PHP/MySQL
-Книги по Assembler
-PHP Fusion MOD'ы
-by Kest
Professional Download System
Реклама
Услуги

Автоматическое добавление статей на сайты на Wordpress, Joomla, DLE
Заказать продвижение сайта
Программа для рисования блок-схем
Инженерный калькулятор онлайн
Таблица сложения онлайн
Популярные статьи
OpenGL и Delphi... 65535
Форум на вашем ... 65535
HACK F.A.Q 65535
Бип из системно... 65535
Гостевая книга ... 65535
Invision Power ... 65535
Содержание сайт... 65535
Организация зап... 65535
Вызов хранимых ... 65535
Программируемая... 65535
Эмулятор микроп... 65535
Подключение Mic... 65535
Создание потоко... 65535
Приложение «Про... 65535
Оператор выбора... 65535
Создание отчето... 65438
Модуль Forms 65201
Пример работы с... 64425
ТЕХНОЛОГИИ ДОСТ... 61857
Имитационное мо... 57766
Реклама
Сейчас на сайте
Гостей: 10
На сайте нет зарегистрированных пользователей

Пользователей: 13,085
новичок: nikita222dolban
Новости
Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ
Delphi, Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog, 3D MAX, Компас 3D
Заказать программу для Windows Mobile, Symbian

Моделирование процесса обработки заданий на вычислительном центре на GP...
База данных склада на Delphi + Схема БД
Моделирование работы участка термической обработки шестерен на GPSS + По...

Реклама



Подписывайся на YouTube канал о программировании, что бы не пропустить новые видео!

ПОДПИСЫВАЙСЯ на канал о программировании
Межапартаментный доступ



Для того чтобы объекты могли находиться в апартаментах, отличных от апартаментов клиента, в СОМ предусмотрена возможность экспорта интерфейсов из одного апартамента и импорта их в другой. Чтобы сделать интерфейс объекта видимым вне апартамента этого объекта, нужно экспортировать этот интерфейс. Чтобы сделать внешний интерфейс видимым внутри апартамента, нужно импортировать этот интерфейс. Когда интерфейс импортирован, то результирующий интерфейсный указатель ссылается на заместитель, доступ к которому разрешен для любого потока в импортирующем апартаменте [1] . Обязанностью заместителя является передача управления обратно в апартамент объекта для того, чтобы удостовериться, что все вызовы метода выполняются в нужном апартаменте. Эта передача управления от одного апартамента к другому называется удaленным вызовом метода (method remoting ) и является механизмом действия всех межпотоковых, межпроцессных и межмашинных связей в СОМ.
По умолчанию удаленный вызов метода использует имеющийся в СОМ протокол передачи ORPC ( Object Remote Procedure Call – вызов объектом удаленной процедуры). СОМ ORPC является упрощенным протоколом MS-RPC (протокол вызова удаленной процедуры Microsoft), производным от DCE ( Distributed Computing Environment – распределенная вычислительная среда). MS-RPC является независимым от протокола механизмом связи, который можно расширять с целью поддержки новых транспортных протоколов (посредством динамически загружаемых транспортных DLL) и новых пакетов аутентификации (посредством динамически загружаемых библиотек поставщика поддержки безопасности Security Support Provider DLL ). СОМ использует наиболее эффективный на доступных транспортных протоколов в зависимости от подобия и типов импортирующего и экспортирующего апартаментов. При связи вне хост-машины СОМ предпочитает UDP ( User Datagram Protocol – протокол передачи дейтаграмм пользователя), хотя и поддерживает большинство общеупотребительных сетевых протоколов [2] . При локальной связи СОМ использует один из нескольких транспортных протоколов, каждый из которых оптимален для определенного типа апартаментов.
СОМ осуществляет передачу интерфейсных указателей через границы апартаментов с помощью особой технологии, именуемой маршалингом ( marshaling) , тo есть расположением в определенном порядке, выстраиванием. Маршалинг интерфейсного указателя – это преобразование его в передающийся байтовый поток, содержимое которого единственным образом идентифицирует объект и его собственный апартамент. Этот байтовый поток является маршалированным состоянием ( marshaled state ) интерфейсного указателя и дает возможность любому апартаменту импортировать интерфейсный указатель и осуществлять вызовы метода на объект. Отметим, что поскольку СОМ имеет дело исключительно с интерфейсными указателями, а не с самими объектами, это состояние маршалинга не представляет собой состояние объекта , а скорее преобразованное в последовательную форму ( serialized ) состояние не зависящей от апартаментов ссылки на объект. Такие маршалированные объектные ссылки просто содержат информацию об установлении связи, которая совершенно не зависит от состояния объекта.
Обычно указатели интерфейса маршалируются неявно как часть стандартной операции СОМ. Когда запрос на внутрипроцессную активацию сделан для класса с несовместимой моделью поточной обработки, СОМ неявно маршалирует интерфейс из апартамента объекта и демаршалирует заместитель в апартаменте клиента. Если сделан запрос на внепроцессную или внехостовую активацию, то СОМ также маршалирует результирующий указатель из апартамента объекта и демаршалирует заместитель для клиента. Если вызовы метода выполняются на заместители, то любые интерфейсные указатели, проходящие в качестве параметров метода, будут маршалированы с целью сделать объектные ссылки доступными в апартаментах и клиента, и объекта. Иногда необходимо маршалировать интерфейсы явным образом из одного апартамента в другой вне контекста запроса на активацию или вызова метода. Для поддержки этого режима в СОМ предусмотрена API-функция низкого уровня CoMarshalInterface , предназначенная для явного маршалинга интерфейсных указателей.
CoMarshalInterface принимает на входе интерфейсный указатель и записывает преобразованное в последовательную форму представление указателя в предоставленный вызывающим объектом байтовый поток. Этот байтовый поток может затем быть передан в другой апартамент, где API-функция CoUnmarshalInterface использует байтовый поток для возвращения интерфейсного указателя, который семантически эквивалентен исходному объекту, и к которому можно легально обращаться в апартаменте, выполняющем вызов функции CoUnmarshalInterface . При вызове CoMarshalInterface вызывающий объект должен указать, насколько далеко может располагаться импортирующий апартамент. В СОМ определен список рекомендуемых расстояний:
typedef enum tagMSHCTX
{
MSHCTX_INPROC = 4,
// in-process/same host
// внутрипроцессный/тот же хост
MSHCTX_LOCAL = 0,
// out-of-process/same host
// внепроцессный/тот же хост
MSHCTX_NOSHAREDMEM = 1,
// 16/32 bit/same host
// 16/32-битный/тот же хост
MSHCTX_DIFFERENTMACHINE = 2
// off-host
// внехостовый
} MSHCTX;



Допускается указывать большую дистанцию, чем необходимо, но для большей эффективности следует использовать по мере возможности корректное значение MSHCTX . CoMarshalInterface также позволяет вызывающему объекту специфицировать семантику маршалинга с помощью следующих специфических флагов:
typedef enum tagMSHLFLAGS
{
MSHLFLAGS_NORMAL,
// marshal once, unmarshal once
// маршалируем один раз, демаршалируем один раз
MSHLFLAGS_TABLESTRONG,
// marshal опсе, unmarshal many
// маршалируем один раз. демаршалируем много раз
MSHLFLAGS_TABLEWEAK,
// marshal once, unmarshal many
// маршалируем один раз, демаршалируем много раз
MSHLFLAGS_NOPING = 4,
// suppress dist. garbage collection
// подавляем ненужный набор дистанций
} MSHLFLAGS;



Нормальный ( normal ) маршалинг, иногда его называют еще маршалингом вызовов ( call marshaling ), означает, что маршалированная объектная ссылка должна быть демаршалирована только один раз, а если нужны дополнительные заместители, то требуются дополнительные вызовы CoMarshalInterface . Табличный ( table ) маршалинг означает, что маршалированная объектная ссылка может быть демаршалирована нуль и более раз без требования дополнительных вызовов CoMarshalInterface . Подробности табличного маршалинга будут описаны далее в этой главе.
Чтобы разрешить маршалинг интерфейсных указателей на различные носители, функция CoMarshalInterface преобразует интерфейсный указатель в последовательную форму через интерфейс типа IStream , предоставляемый вызывающим объектом. Интерфейс IStream моделирует произвольное устройство ввода-вывода и выставляет методы Read и Write . Функция CoMarshalInterface просто вызывает метод Write на предоставленный вызывающим объектом интерфейс типа IStream , не интересуясь тем, куда эти фактические байты будут записаны. Вызывающие объекты могут получить обертку IStream на необработанную ( raw ) память, вызвав API-функцию CreateStreamOnHGlobal :
HRESULT CreateStreamOnHGlobal(
[in] HGLOBAL hglobal,
// pass null to autoalloc
// передаем нуль для автовыдепения памяти
[in] BOOL bFreeMemoryOnRelease,
[out] IStream **ppStm);
С использованием семантики IStream следующий фрагмент кода:
void UseRawMemoryToPrintString(void)
{
void *pv = 0;
// alloc memory
// выделяем память
pv = malloc(13);
if (pv != 0) {
// write a string to the underlying memory
// пишем строку в основную память
memcpy(pv, «Hello, World», 13);
printf((const char*)pv);
// free all resources
// освобождаем все ресурсы free (pv);
}
}



эквивалентен такому фрагменту кода, использующему интерфейс IStream вместо memcpy :
void UseStreamToPrintString(void)
{
IStream *pStm = 0;
// alloc memory and wrap behind an IStream interface
// выделяем память и затем заворачиваем ее в интерфейс
IStream HRESULT hr = CreateStreamOnHGlobal(0, TRUE, &pStm);
if (SUCCEEDED(hr)) {
// write a string to the underlying memory
// записываем строку в память
hr = pStm->Write(«Hello. World», 13, 0);
assert (SUCCEEDED (hr));
// suck out the memory
// извлекаем память
HGLOBAL hglobal = 0;
hr == GetHglobalFromStream(pStm, &hglobal);
assert(SUCCEEDED(hr));
printf((const char*)GlobalLock(hglobal));
// free all resources
// освобождаем все ресурсы
GlobalUnlock(hglobal); pStm->Release();
}
}



API-функция GetHGlobalFromStream позволяет вызывающему объекту получать дескриптор ( handle ) памяти, выделенной функцией CreateStreamOnHGlobal . Использование HGLOBAL сложилось исторически и никоим образом не означает использование разделяемой памяти.
После осмысления всех типов параметров API-функции CoMarshalInterface она выглядит достаточно просто:
HRESULT CoMarshalInterface(
[in] IStream *pStm,
// where to write marshaled state
// куда записывать маршалированное состояние
[in] REFIID riid, // type of ptr being marshaled
// тип маршалируемого указателя
[in, iid_is(riid)] IUnknown *pItf,
// pointer being marshaled
// маршалируемый указатепь
[in] DWORD dwDestCtx,
// MSHCTX for destination apt.
// MSHCTX для апартамента адресата
[in] void *pvDestCtx,
// reserved, must be zero
// зарезервирован, должен равняться нулю
[in] DWORD dwMshlFlags
// normal, vs. table marshal
// нормальный маршалинг против табличного
);



Следующий код маршалирует интерфейсный указатель в блок памяти, пригодный для передачи по сети в любой апартамент:
HRESULT WritePtr(IRacer *pRacer, HGLOBAL& rhglobal)
{ IStream *pStm = 0; гhglobal = 0;
// alloc and wrap block of memory
// выделяем и заворачиваем блок памяти
HRESULT hr = CreateStreamOnHGlobal(0, FALSE, &pStm);
if (SUCCEEDED(hr)) {
// write marshaled object reference to memory
// записываем в память маршалированную объектную ссылку
hr = CoMarshalInterface(pStm, IID_Iracer, pRacer, MSHCTX_DIFFERENTMACHINE, 0, MSHLFLAGS_NORMAL);
// extract handle to underlying memory
// извлекаем дескриптор памяти
if (SUCCEEDED(hr)) hr = GetHGlobalFromStream(pStm, &rhglobal);
pStm->Release();
}
return hr;
}



Рисунок 5.1 иллюстрирует взаимоотношения между интерфейсным указателем и памятью, содержащей маршалированную объектную ссылку. После вызова CoMarshalInterface апартамент объекта готов получить от другого апартамента запрос на соединение. Поскольку был использован флаг MSHCTX_DIFFERENTMACHINE , то импортирующий апартамент может находиться на другой хост-машине.
Для того чтобы декодировать маршалированную объектную ссылку, созданную в предыдущем фрагменте кода, в нормальный интерфейсный указатель, импортирующему апартаменту необходимо вызвать API-функцию CoUnmarshalInterface :
HRESULT CoUnmarshalInterface(
[in] IStream *pStm,
// where to read marshaled state
// откуда читать маршалированное состояние
[in] REFIID riid, // type of ptr being unmaгshaled
// тип демаршалируемого указателя
[out, iid_is(riid)] void **ppv
// where to put unmarshaled ptr
// куда поместить демаршалированный указатель
);



CoUnmarshalInterface просто читает преобразованную в последовательную форму объектную ссылку и возвращает указатель на исходный объект, к которому есть легальный доступ в апартаменте вызывающего потока. Если импортирующий апартамент отличается от того апартамента, который изначально экспортировал интерфейс, то результирующий указатель будет указателем на заместитель. Если по какой-то причине вызов CoUnmarshalInterface осуществлен из исходного апартамента, где располагается объект, то в этом случае будет возвращен указатель на сам объект и не будет создано никакого заместителя. Следующий код переводит маршалированную объектную ссылку в нормальный указатель интерфейса:
HRESULT ReadPtr(HGLOBAL hglobal, IRacer * &rpRacer) {
IStream *pStm = 0; rpRacer = 0;
// wrap block of existing memory passed on input
// заключаем в оболочку блок существующей памяти,
// переданный на вход
HRESULT hr = CreateStreamOnHGlobal(hglobal, FALSE, &pStm);
if (SUCCEEDED(hr)) {
// get a pointer to the object that is legal in this apt.
// получаем указатель на объект, легальный в этом апартаменте
hr = CoUnmarshalInterface(pStm, IID_Iracer, (void**)&rpRacer);
pStm->Release();
}
return hr;
}



Результирующий заместитель будет реализовывать каждый из экспортируемых объектом интерфейсов путем переадресации запросов методов в апартамент объекта.
До появления выпуска СОМ под Windows NT 4.0 формат маршалированной объектной ссылки не был документирован. Для того чтобы позволить сторонним участникам создавать сетевые продукты, совместимые с СОМ, этот формат был документирован для открытого использования в 1996 году и представлен на рассмотрение как проект стандарта для Интернета. На рис. 5.2 показан формат маршалированной объектной ссылки. Заголовок маршалированной объектной ссылки начинается с изысканной сигнатуры «MEOW» (мяу) [3] , а поле флагов указывает на выбранную технологию маршалинга (например, стандартный ( standard ), специальный ( custom )), а также IID интерфейса, содержащегося в ссылке. В случае стандартного маршалинга подзаголовок объектной ссылки показывает, сколько внешних ссылок представляет данная маршалированная ссылка.
Этот счетчик внешних ссылок является частью распределенного протокола «сборки мусора» ( garbage collection ) СОМ и не полностью совпадает со счетчиком ссылок AddRef/Release , который может быть реализован объектом. Интересным элементом объектной ссылки является кортеж ( tuple ) OXID/OID/IPID , который единственным образом идентифицируют интерфейсный указатель. Каждому апартаменту в сети во время его создания присваивается уникальный Идентификатор Экспортера Объектов ( Object Exporter Identifier – OXID ). Этот OXID используется для нахождения сетевой или IPC -адресной информации при первом соединении заместителя с объектом. Идентификатор Объекта ( Object Identifier – OID ) единственным образом определяет идентификационную единицу СОМ в сети и использует CoUnmarshalInterface для поддержания правил идентификации СОМ для заместителей. Идентификатор Интерфейсного Указателя ( Interface Pointer Identifier – IPID ) единственным образом определяет интерфейсный указатель в апартаменте и помещается в заголовок каждого последующего запроса метода. IPID используется для эффективной диспетчеризации запросов ORPC на нужный интерфейсный указатель в апартаменте объекта.
Хотя OXID представляют интерес как логические идентификаторы, сами по себе они бесполезны, так как заместителям нужен какой-нибудь механизм IРС или сетевой протокол для связи с апартаментом объекта. Для перевода OXID в полностью квалифицированные адреса сети или IPC в каждой хост-машине, поддерживающей СОМ, существует специальная служба распознавателя OXID ( OXID Resolver – OR ). Под Windows NT 4.0 OR является частью службы RPCSS . Когда апартамент инициализируется впервые, СОМ назначает OXID и регистрирует его с помощью локального OR . Это означает, что каждый OR знает обо всех работающих апартаментах локальной системы. Кроме того, OR следит за каналом локального IPC-порта для каждого апартамента. Когда CoUnmarshalInterface требуется соединить новый заместитель с апартаментом объекта, то для преобразования OXID в действительный адрес сети или IРС используется локальный OR . Если демаршалированный указатель встречается на той же машине, где находится апартамент объекта, то OR просто ищет OXID в своей локальной OXID -таблице и возвращает локальный IPC-адрес. Если же демаршалированный указатель встречается не на той машине, на которой находится объект, то локальный OR сначала проверяет, встречался ли данный OXID ранее, для чего смотрит в специальном кэше, где хранятся недавно распознанные OXID удаленного доступа. Если OXID ранее не встречался, то он передает запрос OR на хост-машину объекта, используя RPC. Отметим, что маршалированная объектная ссылка содержит адрес хост-машины объекта в формате, подходящем для целого ряда сетевых протоколов, так что OR с демаршалированной стороны знает, куда направлять запрос.
Чтобы распознавать распределенные OXID , служба OR на каждой хост-машине ждет удаленные запросы на распознавание OXID на известном адресе (порт 135 для TCP и UDP) для каждого поддерживаемого сетевого протокола. Когда запрос на распознавание OXID получен из сети, опрашивается локальная таблица OXID . Запрос на распознавание покажет, какие сетевые протоколы поддерживает машина клиента. Если запрошенный процесс из апартамента еще не начал использовать один из запрошенных протоколов, то OR свяжется с СОМ-библиотекой в апартаменте объекта, используя локальный IРС, и инициирует использование запрошенного протокола в процессе объекта. Как только это произойдет, OR занесет новый сетевой адрес апартамента в локальную таблицу OXID . После записи новый сетевой адрес возвращается к OR демаршалирующей стороны, где он кэшируется, чтобы предотвратить дополнительные сетевые запросы на часто используемые апартаменты. Может показаться странным, что контрольное считывание полностью квалифицированных сетевых адресов в ссылке маршалировапного объекта не выполняется сразу. Но уровень косвенности, который допускают не зависящие от протокола идентификаторы апартаментов ( OXID ), разрешает процессу на основе СОМ откладывать использование сетевых протоколов до тех пор, пока они не потребуются. Это особенно важно, поскольку СОМ может иметь дело с множеством различных протоколов (не только TCP), и требовать от каждого процесса слежения за запросами с использованием всех поддерживаемых протоколов было бы чрезвычайно неэффективно. Фактически, если СОМ-процесс никогда не экспортирует указатели внехостовым клиентам, он никогда не потратит вообще никаких сетевых ресурсов.
Опубликовал Kest July 13 2009 14:37:58 · 0 Комментариев · 7005 Прочтений · Для печати

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •


Комментарии
Нет комментариев.
Добавить комментарий
Имя:



smiley smiley smiley smiley smiley smiley smiley smiley smiley
Запретить смайлики в комментариях

Введите проверочный код:* =
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Поделиться ссылкой
Фолловь меня в Твиттере! • Смотрите канал о путешествияхКак приготовить мидии в тайланде?
Загрузки
Новые загрузки
iChat v.7.0 Final...
iComm v.6.1 - выв...
Visual Studio 200...
CodeGear RAD Stud...
Шаблон для новост...

Случайные загрузки
Pro-Download Sys...
Mass Photo Upload
Text3D
MiniTetris [Исход...
AddPage [Исходник...
3d Tank [Исходник...
Delphi 2006 - Спр...
Borland Delphi 8 ...
TrayComp
Разработка клиент...
Error mod
Borland Delphi 6....
Прграммирование в...
Visual Basic for ...
Halcyon
Трассировка прово...
Indy in Depth Глу...
PHP/MySQL для нач...
Использование Lis...
Простой пример ка...

Топ загрузок
Приложение Клие... 100470
Delphi 7 Enterp... 87060
Converter AMR<-... 20078
GPSS World Stud... 12822
Borland C++Buil... 11835
Borland Delphi ... 8604
Turbo Pascal fo... 7039
Visual Studio 2... 4999
Калькулятор [Ис... 4800
FreeSMS v1.3.1 3542
Случайные статьи
Запуск формы для р...
Local object types...
Hydac
Проектирование гра...
Что создает функци...
Аварийное восстано...
Шаблонизатор на PH...
Функция list1
Подсказки к некото...
реестр Windows 200...
Поддержка модема в...
Нам нужна такая ре...
Генерация кода по ...
Подготовка жидкокр...
Идеальная ЛВС
Процедуры двоичной...
ОБЛАСТИ ВИДИМОСТИ ...
В этой главеГруппо...
Must be in 8087 mo...
Некоторые миры
Переход в графичес...
Предостережение: к...
Cобытийное моделир...
Где мы находимся?
Чтение сообщения и...
Статистика



Друзья сайта
Программы, игры


Полезно
В какую объединенную сеть входит классовая сеть? Суммирование маршрутов Занимают ли таблицы память маршрутизатора?