Реализация вызова удаленных процедур по технологии DCOM

 

Введение


Распределенные приложения обладают рядом потенциальных преимуществ по сравнению с локальными. Среди этих преимуществ - более высокая производительность, отказоустойчивость, масштабируемость и приближение к пользователю. Сетевая операционная система составляет основу любой вычислительной сети. Каждый компьютер в сети в значительной степени автономен, поэтому под сетевой операционной системой в широком смысле понимается совокупность операционных систем отдельных компьютеров, взаимодействующих с целью обмена сообщениями и разделения ресурсов по единым правилам - протоколам. В узком смысле Сетевая операционная система - операционная система со встроенными возможностями для работы в компьютерных сетях.

К таким возможностям можно отнести:

поддержку сетевого оборудования

поддержку сетевых протоколов

поддержку протоколов маршрутизации

поддержку фильтрации сетевого трафика

поддержку доступа к удалённым ресурсам, таким как принтеры, диски и т.п. по сети

поддержку сетевых протоколов авторизации

наличие в системе сетевых служб, позволяющих удалённым пользователям использовать ресурсы компьютера

В сетевой операционной системе отдельной машины можно выделить несколько частей (рисунок 1):

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

Средства предоставления собственных ресурсов и услуг в общее пользование - серверная часть ОС (сервер). Эти средства обеспечивают, например, блокировку файлов и записей, что необходимо для их совместного использования; ведение справочников имен сетевых ресурсов; обработку запросов удаленного доступа к собственной файловой системе и базе данных; управление очередями запросов удаленных пользователей к своим периферийным устройствам.

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

Коммуникационные средства ОС, с помощью которых происходит обмен сообщениями в сети. Эта часть обеспечивает адресацию и буферизацию сообщений, выбор маршрута передачи сообщения по сети, надежность передачи и т.п., то есть является средством транспортировки сообщений.

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

Рис. 1 - Функционирование сетевой операционной системы


Для осуществления сетевых взаимодействий программ и служб сетевых ОС был разработан механизм вызова удалённых процедур. Вызов удалённых процедур (от англ. Remote Procedure Call (RPC)) - класс технологий, позволяющих компьютерным программам вызывать функции или процедуры в другом адресном пространстве (как правило, на удалённых компьютерах). Обычно, реализация RPC технологии включает в себя два компонента: сетевой протокол для обмена в режиме клиент-сервер и язык сериализации объектов (или структур, для необъектных RPC). Различные реализации RPC имеют очень отличающуюся друг от друга архитектуру и разнятся в своих возможностях: одни реализуют архитектуру SOA, другие CORBA или DCOM.

Характерными чертами вызова локальных процедур являются:

Асимметричность, то есть одна из взаимодействующих сторон является инициатором;

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

Рассмотрим технологию, в которой реализуется RPC DCOM.- это распределенная модель СОМ (Distributed СОМ, DCOM) корпорации Microsoft. Как можно понять из ее названия, модель DCOM выросла из модели компонентных объектов (Component Object Model, COM). С самого начала СОМ разрабатывалась с учетом обеспечения поддержки распределенных сред, т.е. способности клиента создавать объекты на других машинах и вызывать их методы по сети. Эти планы стали реальностью в 1996 году после выпуска распределенной СОМ (Distributed СОМ - DCOM). DCOM позволяет клиенту создавать и использовать объекты как на удаленных системах, так и на локальной. Более того, клиент может даже не осознавать различия между этими двумя случаями. Подобно тому, как клиенты СОМ имеют прозрачный доступ к объектам в динамических библиотеках и локальных процессах, DCOM обеспечивает прозрачный доступ к объектам в удаленных процессах.

В данной курсовой работе ставится задача смоделировать подсистему сетевой операционной системы: вызов удаленных процедур(RPC) по технологии DCOM. А именно, клиентское приложение должно иметь возможность запустить серверное приложение на удаленном компьютере и вызвать необходимые методы, установить соответствующие свойства.

1. Теоретическая часть


.1 Описание существующих технологий, поддерживающих концепцию распределенных объектных систем


На сегодняшний день выделяются три различные технологии, поддерживающие концепцию распределенных объектных систем. Это технологии RMI, CORBA и DCOM. (Remote Method Invocation, т.e. вызов удаленного метода) является продуктом компании JavaSoft и реализует распределенную модель вычислений. RMI позволяет клиентским и серверным приложениям через сеть вызывать методы клиентов/серверов, выполняющихся в Java Virtual Machine. Хотя RMI считается легковесной и менее мощной, чем CORBA и DCOM тем не менее, она обладает рядом уникальных свойств, таких как распределенное, автоматическое управление объектами и возможность пересылать сами объекты от машине к машине.

На Рис.2 показаны основные компоненты архитектуры RMI.


Рис. 2 - Модель RMI

Stub и Server Stub порождены от общего интерфейса, но различие между ними в том, что client stub служит просто для подсоединения к RMI Registry, а server stub используется для связи непосредственно с функциями сервера.

Технология CORBA (Common Object Request Broker Architecture), разрабатываемая OMG (Object Managment Group) с 1990-го года, позволяет вызывать методы у объектов, находящихся в сети где угодно, так, как если бы все они были локальными объектами.

На Рис.3 показана основная структура CORBA.


Рис. 3 - Модель CORBA

Invocation Interface (DII): позволяет клиенту находить сервера и вызывать их методы во время работы системы.Stubs: определяет, каким образом клиент производит вызов сервера.Interface: общие как для клиента, так и для сервера сервисы.Skeleton: обеспечивает статические интерфейсы для объектов определенного типа.Skeleton Inerface: общие интерфейсы для объектов, независимо от их типа, которые не были определены в IDL Skeleton.Adapter: осуществляет коммуникационное взаимодействие между объектом и ORB.

Технология DCOM (Distributed Component Object Model) была разработана компанией Microsoft в качестве решения для распределенных систем в 1996-м году. Сейчас DCOM является главным конкурентом CORBA, хотя контролируется он теперь уже не Microsoft, а группой TOG (The Open Group), аналогичной OMG. Вкратце, DCOM представляет собой расширение архитектуры COM до уровня сетевых приложений.


Рис. 4 - Архитектура DCOM


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

Достоинства и недостатки DCOM:

Достоинства

Языковая независимость;

Динамический/статический вызов;

Динамическое нахождение объектов;

Масштабируемость;

Недостатки

Сложность реализации;

Зависимость от платформы;является лишь частным решением проблемы распределенных объектных систем. Он хорошо подходит для Microsoft-ориентированных сред. При необходимости работы с архитектурой, отличной от WindowsNT и Windows95, DCOM перестает быть оптимальным решением проблемы. На сегодняшнем день, DCOM хорош лишь в качестве решения для систем, ориентированных исключительно на продукты Microsoft. Большие нарекания вызывает также отсутствие безопасности при исполнении ActiveX компонент, что может привести к неприятным последствиям.

Достоинства и недостатки RMI:

Достоинства

Быстрое и простое создание;

Java-оптимизация;

Динамическая загрузка компонент-переходников;

Возможность передачи объектов по значению;

Встроенная безопасность;

Недостатки

Поддержка только одного языка - Java;

Свой собственный, не IIOP-совместимый протокол взаимодействия;

Трудность интегрирования с существующими приложениями;

Плохая масштабируемость;

Благодаря своей легкоиспользуемой Java-модели, RMI является самым простым и самым быстрым способом создания распределенных систем. RMI - хороший выбор для создания RAD-компонент и небольших приложений на языке Java. Конечно, RMI не такая мощная технология, как DCOM или CORBA. В частности, RMI использует свой родной, не CORBA/IIOP-совместимый протокол передачи JRMP и может взаимодействовать лишь с другими Java объектами. Поддержка только одного языка делает невозможным взаимодействие с объектами, написанными не на языке Java. Тем самым, роль RMI в создании больших, масштабируемых промышленных систем, снижается.

Достоинства и недостатки CORBA:

Достоинства

Платформенная независимость;

Языковая независимость;

Динамические вызовы;

Динамическое обнаружение объектов;

Масштабируемость;

CORBA-сервисы;

Широкая индустриальная поддержка;

Недостатки

Нет передачи параметров `по значению';

Отсутствует динамическая загрузка компонент-переходников;

К основным достоинствам CORBA можно отнести межъязыковую и межплатформенную поддержку. Хотя CORBA-сервисы и отнесены к достоинствам технологии CORBA, их в равной степени можно одновременно отнести и к недостаткам CORBA, ввиду практически полного отсутствия их реализации.


1.2 Описание технологии DCOM


Обычные СОМ объекты имеют один важный недостаток - их можно использовать только в пределах отдельного компьютера, т.е. и СОМ-сервер и СОМ-клиент должны работать в рамках одной операционной системы. Их нельзя разместить на разных компьютерах и организовать общение через сетевую среду, т.е. в рамках технологии обычной СОМ нельзя создать распределенную программную систему.

Для того, чтобы устранить этот недостаток, специалисты Microsoft разработали распределенную модель СОМ - DCOM. Модель DCOM расширяет возможности СОМ, позволяя обращаться к СОМ объектам в режиме удаленного доступа.

Распределенная модель DCOM разработана для того, чтобы обеспечить взаимодействие между СОМ объектами в режиме удаленного доступа. Это позволяет СОМ серверу и СОМ клиентам располагаться на разных компьютерах и связываться по сети. По сути, механизм поддержки DCOM реализует те же задачи, что и механизм поддержки СОМ, но дополнительно он обеспечивает безопасность приложений в сетевой среде. Создание DCOM стало возможным в результате расширения возможностей механизма удаленного вызова процедур RPC и превращение его в объектный (Object) RPC. В настоящее время эту модель можно рассматривать как средство реализации распределенных многоплатформенных приложений.

В модели DCOM используется концепция "прозрачности размещения", которая подразумевает, что можно, не изменяя программного кода, выполнить приложение СОМ сервера на разных компьютерах сети. При этом ни приложение-сервер, ни приложение-клиент не "знают", на каком компьютере фактически работает "собеседник". Они могут выполняться на одном компьютере, на разных компьютерах локальной сети, или даже на разных компьютерах, подключенных к глобальной сети, например Internet. Приложение-клиент "узнает" о существовании сервера из данных в системном реестре, которые могут быть легко изменены.

Но за такую "прозрачность" приходится платить. В данном случае приходится предпринимать дополнительные меры для обеспечения безопасности. В средствах поддержки DCOM эта задача решается в рамках сетевой системы доменов, уже давно реализованной в Microsoft.

Клиентские и серверные DCOM-приложения должны следовать правилам аутентификации и авторизации. Это означает, что приложение должно пройти через определенную процедуру регистрации при попытке получить доступ к компьютеру, на котором выполняется серверное приложение. Сервер должен аутентифицировать (идентифицировать) клиента - проверить, действительно ли он является тем, за кого себя выдает, и авторизировать доступ - выяснить, имеет ли пользователь необходимые привилегии доступа.

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

Главной проблемой при программировании DCOM-приложений является как раз подсистема обеспечения безопасности.

модель DCOM базируется на модели СОМ. Целью создания СОМ была поддержка разработки компонентов, которые могли бы динамически активизироваться и взаимодействовать друг с другом. Компонент в СОМ - это исполняемый код, содержащийся в динамически компонуемой библиотеке (DLL) или исполняемой программе.

Сама по себе модель СОМ существует в виде библиотек, компонуемых с процессом. Изначально она разрабатывалась для поддержки так называемых составных документов (compound documents). Как мы говорили в главе 3, составные документы - это документы, построенные из разнородных частей, таких как текст (форматированный), изображения, электронные таблицы и т.п. Каждая из этих частей может быть отредактирована при помощи ассоциированного с ней приложения.

Для поддержки бесчисленного множества составных документов Microsoft нужен был обобщенный метод для разделения отдельных частей и объединения их в единую сущность. Вначале это привело к технологии связывания и внедрения объектов (Object Linking and Embedding, OLE), Первая версия OLE использовала для передачи информации между частями документа примитивный и негибкий способ обмена сообщениями. Вскоре она была заменена следующей версией, также называвшейся OLE, но построенной на базе более гибкого механизма СОМ, что привело к появлению структуры, представленной на рис. 5.

Рис. 5 - Общая структура ActiveX, OLE и COM


На рисунке также показан элемент ActiveX - этим термином в настоящее время называют все, что относится к OLE, плюс некоторые новшества, к которым относят гибкую (как правило) способность компонентов выполняться в разных процессах, поддержку сценариев и более или менее стандартную группировку объектов в так называемые элементы управления ActiveX. Среди экспертов по DCOM (даже внутри Microsoft) не существует согласия по вопросу о точном определении ActiveX, поэтому мы даже не будем пытаться дать подобное определение.

Модель DCOM добавила к этой структуре весьма существенную вещь - способность процесса работать с компонентами, размещенными на другой машине. Однако базовый механизм обмена информацией между компонентами, принятый в DCOM, очень часто совпадает с соответствующими механизмами СОМ. Другими словами, для программиста разница между СОМ и DCOM часто скрыта за различными интерфейсами. Как мы увидим, DCOM в первую очередь предоставляет прозрачность доступа. Другие виды прозрачности менее очевидны.

Как и в CORBA, объектная модель в DCOM построена на реализации интерфейсов. Грубо говоря, объект DCOM - это просто реализация интерфейса. Один объект может реализовывать одновременно несколько интерфейсов. Однако в отличие от CORBA в DCOM имеются только бинарные интерфейсы (binary interfaces). Такой интерфейс, в сущности, представляет собой таблицу с указателями на реализации методов, которые являются частью интерфейса. Разумеется, для определения интерфейса по-прежнему удобно использовать специальный язык определения интерфейса (IDL). В DCOM также имеется такой язык под названием MIDL (Microsoft IDL - язык IDL от Microsoft), при помощи которого генерируются бинарные интерфейсы стандартного формата.

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


Рис. 6 - Разница между интерфейсами

Каждый интерфейс в DCOM имеет уникальный 128-битный идентификатор, который называется идентификатором интерфейса (Interface Identifier, IID), Каждый IID абсолютно уникален, не существует двух интерфейсов с одинаковым идентификатором IID. Этот идентификатор создается путем комбинирования большого случайного числа, локального времени и адреса сетевого интерфейса текущего хоста. Вероятность того, что два сгенерированных индикатора совпадут, практически равна нулю.

Объект DCOM создается как экземпляр класса. Чтобы создать такой объект, необходимо иметь доступ к соответствующему классу. Для этой цели DCOM содержит объекты класса (class objects). Формально таким объектом может быть все, что поддерживает интерфейс IClassFactory. Этот интерфейс содержит метод Createlnstance, который похож на оператор new в языках C++ и Java. Вызов метода Createlnstance для объекта класса приводит к созданию объекта DCOM, содержащего реализацию интерфейсов объекта класса.

Таким образом, объект класса представляет собой коллекцию объектов одного типа, то есть реализующих один и тот же набор интерфейсов. Объекты, принадлежащие к одному классу, обычно различаются только в части текущего состояния. Путем создания экземпляров объекта класса становится возможным обращение к методам этих интерфейсов. В DCOM на любой объект класса можно сослаться по его глобальному уникальному идентификатору класса (Class Identifier, CLSID).

Все объекты реализуют стандартный объектный интерфейс lUnknown. Когда путем вызова Createlnstance создается новый объект, объект класса возвращает указатель на этот интерфейс. Самый важный метод, содержащийся в lUnknown, - метод Querylnterface, который на основании IID возвращает указатель на другой интерфейс, реализованный в объекте.

Важное отличие от объектной модели CORBA состоит в том, что все объекты в DCOM нерезидентные. Другими словами, как только у объекта не остается ссылающихся на него клиентов, этот объект удаляется. Подсчет ссылок производится путем вызова методов AddRef и Release, входящих в интерфейс lUnknown. Наличие исключительно нерезидентных объектов делает невозможным хранение каждым из объектов своего глобально уникального идентификатора. По этой причине объекты в DCOM могут вызываться только по указателям на интерфейсы. Соответственно, как мы увидим позднее, для передачи ссылки на объект другому процессу необходимо предпринять специальные меры. также требует динамического обращения к объектам. Объекты, запросы к которым могут создаваться динамически, во время выполнения, должны иметь реализацию интерфейса IDispatch. Этот интерфейс подобен интерфейсу динамического обращения (DII) в системе CORBA.


1.3 Разработка модели подсистемы СОС


Вызов RPC Результат вызова RPC



Рис. 7 - Описание подсистемы и модели как черного ящика


Общее описание подсистемы вызова удаленных процедур по технологии DCOMерверы автоматизации могут выполняться как в адресном пространстве контроллера, так и в собственном адресном пространстве.

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

Один из часто встречающихся примеров практического использования удаленного доступа - использование удаленного запуска MS Excel, установленного на одном-единственном компьютере локальной сети, для печати отчетов и диаграмм. В этом случае можно снизить требования к ресурсам рабочих станций, содержащих приложения-контроллеры Excel (и сэкономить некоторые средства на покупке нескольких копий Excel).

Второй пример использования удаленного запуска серверов автоматизации, вызывающий в последнее время немалый интерес разработчиков информационных систем - это пример трехзвенной информационной системы с "тонким" клиентом - контроллером автоматизации, и сервером автоматизации (в данном случае он иногда называется сервером приложений), предоставляющим "тонкому" клиенту сервисы, связанные с доступом к данным, содержащимся, в свою очередь, в какой-либо серверной СУБД. В этом случае, помимо экономии ресурсов компьютеров, содержащих контроллеры, имеется еще одно преимущество, связанное с тем, что для доступа к данным используется программное обеспечение, требующее отдельной установки, сложной настройки и поддержки, такое как клиентская часть серверной СУБД, а также, как правило, библиотека Borland Database Engine, драйверы SQL Links, а иногда и ODBC-драйверы. Если это программное обеспечение используется только сервером, но не используется контроллерами, сопровождение такой системы значительно облегчается.

Использование интерфейсов

Единственным способом взаимодействия клиента c COM-объектом является использование интерфейсов. Интерфейс связан с группой функций, связанных, в свою очередь, с COM-объектом, и не содержит их реализации. На этапе выполнения интерфейс всегда представляется указателем, идентифицируемым с помощью идентификатора IID(Interface Identifier - по существу, это тот же GUID) и указывающим на другой указатель, который, в свою очередь, указывает на таблицу, содержащую адреса реализации каждой функции из этой группы (рис.8).


Рис. 8 - Структура интерфейса


Эта структура позволяет обеспечить маршалинг - пересылку указателя между процессами (и в общем случае между компьютерами).

Реализация интерфейса COM-объекта представляет собой создание в памяти подобной структуры и предоставление указателя на нее. Фактически такая структура похожа на структуру, используемую для построения таблиц виртуальных функций в C++, поэтому таблица указателей на функции в этой структуре иногда называется "vtable" (или таблицей виртуальных методов).

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

Когда клиенту требуется COM-объект, он пытается найти сервер, посылает серверу запрос на создание объекта, а затем получает от него указатель на исходный интерфейс, с помощью которого можно получить дополнительные указатели на другие интерфейсы этого объекта.находит местоположение сервера на основании записи в реестре, загружает его в оперативную память, запрашивает у сервера нужный объект (инициируя его создание) и получает указатель на интерфейс. Если сервер и клиент выполняются в разных процессах, COM автоматически передает указатель на интерфейс в процесс клиента.

Маршалинг и удаленный доступ

Если сервер является внутренним ("in-process"), т.е. выполненным в виде DLL, она загружается в адресное пространство клиента с помощью функции Win32 API LoadLibrary. В этом случае значение указателя на интерфейс непосредственно доступно клиенту.

Если сервер локальный, COM использует функцию CreateProcess, загружая исполняемый файл и инициализируя COM в адресном пространстве последнего. Затем COM в процессе сервера связывается с COM в процессе клиента каким-либо доступным способом. В этом случае обычно нет возможности передать клиенту точное значение указателя на интерфейс, так как это указатель на объект в другом адресном пространстве. В этом случае используется маршалинг, создающий так называемый "marshalling packet", содержащий необходимую информацию для соединения с процессом, в котором создан объект. Этот пакет создается с помощью функции COM API CoMarshalInterface, затем он передается процессу клиента любым доступным способом, где другая функция CoUnMarshalInterface превращает этот пакет в указатель на интерфейс. В действительности маршалинг создает в обоих адресных пространствах два объекта: "stub"("заглушка") - представитель клиента в адресном пространстве сервера, имеющий дело с реальным указателем на интерфейс, и "proxy" - представитель сервера в адресном пространстве клиента. Эти два объекта соединяются между собой каким-либо доступным способом, и представитель сервера передает клиентскому процессу указатель на интерфейс. Сходная технология используется при осуществлении вызовов удаленных процедур (RPC - Remote Procedure Calls).

Естественно, proxy-объект не содержит реализации интерфейса. Все аргументы вызываемых функций помещаются в пакет, передаваемый stub-объекту с использованием RPC. Stub-объект распаковывает переданные аргументы, помещает их в стек и обращается к реальному объекту, используя существующий указатель на интерфейс. Результат выполнения функции упаковывается в пакет и посылается proxy-объекту, который распаковывает его и передает клиенту.

В случае сервера, расположенного на удаленном компьютере, при обращение к серверу COM соединяется со специальным резидентным процессом удаленного компьютера, контролирующим удаленный запуск сервисов на нем. Этот процесс, называемый иногда Service Control Manager - SCM, осуществляет запуск сервера на удаленном компьютере и возвращает указатель на интерфейс клиентскому компьютеру и клиентскому процессу. В качестве SCM могут быть использованы средства различных производителей, как основанные непосредственно на технологии Microsoft DCOM (Distributed COM), так и являющиеся расширением этой технологии (например, ObjectFactory из комплекта поставки OLEnterprise корпорации Inprise). Обязательное наличие такого процесса (и возможностей его конфигурации) диктуется элементарными соображениями безопасности - было бы неестественно, если бы любой пользователь сети мог запустить любой процесс на любом из компьютеров, к этой сети подключенных. В остальном маршалинг осуществляется точно так же, как и в случае локального сервера, за исключением того, что proxy и stub, общаясь с помощью того же самого механизма RPC, физически находятся на разных компьютерах (рис. 9).


Рис. 9 - Осуществление удаленного доступа к серверу автоматизации

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

Для того чтобы действительно активизировать объект, то есть гарантировать, что он создан и помещен в процесс, из которого будет в состоянии принимать обращения к методам, DCOM использует реестр Windows в комбинации со специальным процессом - менеджером управления службами (Service Control Manager, SCM). Кроме всего прочего, реестр используется для записи отображения идентификаторов классов (CLSID) на локальные имена файлов, содержащих реализации классов. Чтобы создать объект, процесс сначала должен убедиться, что соответствующий объект класса загружен.

Если объект выполняется на удаленном хосте, дело происходит иначе. В этом случае клиент контактирует с менеджером управления службами этого хоста, который представляет собой процесс, ответственный за активизацию объектов, подобно хранилищу реализаций в CORBA. SCM этого удаленного хоста просматривает свой локальный реестр в поисках файла, ассоциированного с CLSID, после чего запускает процесс, содержащий этот объект. Сервер выполняет мар- шалинг указателя на интерфейс и возвращает его клиенту, который выполняет демаршалинг указателя и передает его заместителю.

Процесс клиента получает доступ к SCM и реестру, что помогает ему найти удаленный объект и выполнить привязку к нему. Клиенту предлагается заместитель, реализующий интерфейсы этого объекта.

Серверы DCOM

Предполагается, что объекты DCOM являются более или менее самодостаточными в том смысле, что различные возможности, которые в CORBA предоставляет переносимый адаптер объектов, жестко закодированы в каждом объекте DCOM. DCOM предлагает стандартный способ активизации объектов, в том числе и размещенных на удаленном хосте.

На хосте, поддерживающем объекты DCOM, должен выполняться уже упоминавшийся ранее менеджер управления службами (Service Control Manager, SCM). SCM отвечает за активизацию объектов, которая производится следующим образом. Предположим, что клиент владеет CLSID объекта класса. Чтобы создать новый объект, он передает этот идентификатор CLSID в свой локальный реестр, где выполняется поиск хоста, на котором должен находиться нужный сервер объектов. Затем CLSID передается менеджеру SCM, ассоциированному с найденным хостом. В поисках файла, позволяющего загрузить объект класса, который может создавать экземпляры нового объекта, SCM ищет этот идентификатор CLSID уже в своем локальном реестре. обычно начинает выполнение нового процесса с загрузки найденного объекта класса, после чего создает экземпляр объекта. В SCM регистрируется также порт, из которого «свежеиспеченный» сервер будет получать входящие запросы, а также идентификатор нового объекта. Эта информация привязки возвращается клиенту, который после ее получения может работать с сервером объекта напрямую, без вмешательства SCM.

Такой подход оставляет решение всех вопросов, связанных с управлением объектами на сервере, разработчику. Чтобы немного облегчить ему жизнь, DCOM предоставляет средства управления объектами. Одно из таких средств носит название активизации «на лету» («just-in-time» activation), или JIT-активизации (JIT-activation). Под этим названием скрывается механизм, при помощи которого сервер может управлять активизацией и удалением объектов. Он работает следующим образом.

Обычно объект активизируется в результате запроса клиента на создание экземпляра нового объекта данного класса. Сервер объекта хранит объект в памяти до тех пор, пока существуют клиенты, хранящие ссылку на этот объект. Однако при JIT-активизации сервер может удалить объект тогда, когда захочет. Так, например, если сервер обнаруживает, что у него не осталось памяти, он может освободить место для новых объектов, удалив старые.

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

Защита

Как и в CORBA, система защиты DCOM в основном обеспечивает защиту обращений к объектам. Однако способ реализации защищенных обращений здесь абсолютно иной. Хотя DCOM чаще всего входит в одну из операционных систем семейства Windows, разработчики DCOM совершенно оправданно решили по возможности отделить защиту DCOM от служб защиты Windows. Таким образом они сохранили возможность реализации DCOM на других операционных системах с сохранением защиты обращений.

В DCOM существует два направления реализации защиты. Важная роль в защите DCOM отводится реестру, при помощи которого осуществляется декларативная защита. Кроме того, защита может быть реализована и программным путем, в том смысле, что приложение может само решать вопросы контроля доступа и аутентификации.


1.4 Механизм работы RPC


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

Идея, положенная в основу RPC, состоит в том, чтобы сделать вызов удаленной процедуры выглядящим по возможности также, как и вызов локальной процедуры. Другими словами - сделать RPC прозрачным: вызывающей процедуре не требуется знать, что вызываемая процедура находится на другой машине, и наоборот. достигает прозрачности следующим путем. Когда вызываемая процедура действительно является удаленной, в библиотеку помещается вместо локальной процедуры другая версия процедуры, называемая клиентским стабом (stub - заглушка). Подобно оригинальной процедуре, стаб вызывается с использованием вызывающей последовательности, так же происходит прерывание при обращении к ядру. Только в отличие от оригинальной процедуры он не помещает параметры в регистры и не запрашивает у ядра данные, вместо этого он формирует сообщение для отправки ядру удаленной машины.

Этапы выполнения RPC

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

Затем параметры должны быть преобразованы в соответствующий формат и вставлены в буфер сообщения. К этому моменту сообщение готово к передаче, поэтому выполняется прерывание по вызову ядра.


Рис. 10 - Механизм работы RPC


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

На стороне сервера поступающие биты помещаются принимающей аппаратурой либо во встроенный буфер, либо в оперативную память. Когда вся информация будет получена, генерируется прерывание. Обработчик прерывания проверяет правильность данных пакета и определяет, какому стабу следует их передать. Если ни один из стабов не ожидает этот пакет, обработчик должен либо поместить его в буфер, либо вообще отказаться от него. Если имеется ожидающий стаб, то сообщение копируется ему. Наконец, выполняется переключение контекстов, в результате чего восстанавливаются регистры и карта памяти, принимая те значения, которые они имели в момент, когда стаб сделал вызов receive.

Теперь начинает работу серверный стаб. Он распаковывает параметры и помещает их соответствующим образом в стек. Когда все готово, выполняется вызов сервера. После выполнения процедуры сервер передает результаты клиенту. Для этого выполняются все описанные выше этапы, только в обратном порядке.


Рис. 11 Этапы выполнения процедуры RPC

При удаленном вызове процедуры в распределенной системе происходят следующие действия:

. Процедура клиента вызывает стаб как обычную процедуру. Стаб упаковывает параметры (маршализация, marshaling).

. Стаб обращается к ядру ОС.

. Ядро посылает сообщение на удаленную машину (ядру удаленного ПК).

. Передача полученного сообщения скелетону серверного процесса.

. Распаковка параметров (демаршализация, unmarshaling). Вызов требуемой процедуры.

. Процедура на сервере выполняется. Возвращает результаты скелетону.

. Скелетон упаковывает результат.

. Передача результата ядру.

. Ядро сервера передает сообщение по сети ядру клиента.


. Ядро клиента обращается к стабу. Стаб распаковывает полученный результат.

. Передача от стаба клиентскому процессу.

Выполнение удаленного вызова процедуры представлено на Рис. 12.

Рис. 12 - Выполнение удаленного вызова процедуры

2. Специальная часть


.1 Постановка задачи


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

В качестве примера предметной области выберем несложный объект с изменяемыми параметрами - вычислитель матрицы с изменяемыми элементами и их количеством.


.2 Разработка и определение параметров приложения


Вычислитель матрицы - устройство управления объектом, позволяющее вводить в таблицу значения матрицы и производить над ними арифметические операции (вычислять детерминант).

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

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

Рис. 13 - Вычислитель матрицы


Класс матрицы Matrix:


Таблица 1 - Данные класса Matrix

НазваниеТипНазначениеMIntКоличество строкNIntКоличество столбцовA[]intМассив, хранящий значения матрицыpGenRandGen*Переменная класса RandGen

Таблица 2 - Функции класса Matrix

НазваниеТипНазначениеMatrixКонструктор ~ MatrixДеструкторSetSizevoidУстанавливает размеры FillvoidУстанавливает конкретное значение всем ячейкамFindMaxintНаходит максимальный элемент матрицыFindMinintНаходит минимальный элемент матрицыSetElemvoidУстанавливает значение элементу матрицыGetMintПолучает количество строкGetNintПолучает количество столбцовGetElemintПолучает элемент матрицыSetGenvoidУстанавливает сгенерированное случайное значениеFillRandvoidУстанавливает случайные значения в элементы матрицыDetermintВычисляет детерминантDelLineMatrix&Удаление строкиDelColMatrix&Удаление столбца

Класс генератора случайных чисел RandGen:

Данные класса:


НазваниеТипНазначениеminIntМинимальное значениеWidthintМаксимальное значение

Функции класса:


НазваниеТипНазначениеRandGenКонструктор ~ RandGenДеструкторInitvoidОбнуление генератораGetintВозвращает случайное значение из границ min, maxSetIntervalvoidУстанавливает границыGetMinintПолучает минимальное значениеGetMaxintПолучает максимальное значениеGetWidthintПолучить ширинуКласс отрисовки матрицы View:

Данные класса:


НазваниеТипНазначениеSizeXIntДлина ячейкиSizeYintШирина ячейкиpMatrMatrix *Переменная класса Matrix

Функции класса:


НазваниеТипНазначениеViewКонструктор ~ ViewДеструкторDrawvoidОтрисовкаGetSizeXintПолучает длину ячейкиGetSizeYintПолучает ширину ячейкиSetMatrixvoidУстанавливает переменной значение типа матрицыSetSizeXvoidУстанавливает длину ячейкиSetSizeYvoidУстанавливает ширину ячейки

Анализ характерного поведения.

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

Матрица должна иметь:

Длину (количество столбцов).

Ширину(количество строк).

Как и все оконные элементы управления, вычислитель матрицы можно размещать на форме и изменять её размеры.

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

Объект, включающий в себя все эти части должен обладать следующими функциями:

Средство для рисования

Возможность ввести значение в любую ячейку

Добавлять строку

Добавлять столбец

Устанавливать ширину столбцов и строк

Изменять свои размеры

Возможность заполнить матрицу случайными значениями

Возможность вычислить минимальное и максимальное значение

Возможность вычислить детерминант.

На основе анализа предметной области были написаны следующие классы:

Класс матрицы.Matrix

{:

Matrix();(Matrix &m);

~Matrix();

void SetSize(int m, int n);Fill(int val);FindMax();FindMin();SetElem(int i, int j, int val);GetM();GetN();GetElem(int i, int j);SetGen(RandGen * pG);FillRand();Determ();& DelLine(int k);& DelCol(int k);

private:

int M;N;** A;* pGen;

};

. Класс генератора случайных чисел.

class RandGen

{:

RandGen();

~RandGen();Init();Get();

void SetInterval(int i_min, int i_max);

int GetMin();GetMax();:min;max;

};

Класс отрисовки матрицы.

class View

{:();

~View();Draw(TCanvas * Canvas);SetMatrix(Matrix * pM);GetSizeX();GetSizeY();SetSizeX(int size){SizeX = size;}SetSizeY(int size){SizeY = size;}:SizeX;SizeY;

Matrix * pMatr;

};


2.3 Формализация требований к программному средству


Программа должна состоять из двух модулей - сервера автоматизации и клиента.

Сервер и клиент должны поддерживать взаимодействие как в пределах одного компьютера, так и по сети.

Использование технологии DCOM при реализации.

Основные требования к серверу:

Динамическое отображение изменений характеристик клиента.

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

Основные требования к клиенту:

Возможность установления/разрыва соединения с сервером.

Наличие методов и средств изменения параметров сервера.


.4 Выбор инструмента разработки и его обоснование


В качестве языка программирования был выбран объектно-ориентированный язык С++. Среда разработки - зарекомендовавший себя продукт Borland Builder C++ 6.

2.3 Реализация приложения


Сервер.

В сервере необходимо реализовать графическое отображение объекта и его характеристик.


Рис. 14 - Внешний вид приложения сервера


Для того, чтобы определенные данные сервера были доступны для внешнего мира, воспользуемся библиотекой типов. А именно - зададим определенные свойства (и опишем методы доступа к ним):

Свойства:

Количество строк

Количество столбцов

Длина ячейки

Ширина ячейки

Минимальное значение элемента

Максимальное значение элемента

Методы:

установить размеры ячейки

установить конкретное значение всем ячейкам

получить максимальный элемент матрицы

получить минимальный элемент матрицы

получить количество строк

получить количество столбцов

получить элемент матрицы

установить случайное сгенерированное значение

вычислить детерминант.

При изменении свойств из клиентского приложения на сервере отображается изменение параметров реостата.

Далее сервер обязательно необходимо зарегистрировать в операционной системе, чтобы она знала о его существовании и местоположении.

После этого пользователь определяет интерфейс посредством библиотеки типов.


Рис. 15 - Определение интерфейса сервера в библиотеке типов


Клиент:

В клиенте реализована возможность соединения/разъединения связи с сервером, изменение свойств сервера.

Изменение количества строк и столбцов, а также конкретных значений элементов реализована с помощью соответствующих текстовых полей.


Рис. 16 - Схема взаимодействия для локального и удаленного вариантов приложений

приложение локальный параметр

Описание взаимодействия клиента и сервера:

Для осуществления взаимодействия в клиенте имеются две кнопки:

выполнить подключение

прекратить подключение

При нажатии на первую кнопку вызывается функция CreateOleObject() с параметром Kurs.AmpAuto - имя созданного нами com-объекта (от клиента поступает запрос операционной системе для установления связи с сервером. Операционная система ищет в своем реестре объект, указанный в запросе (Kurs. AmpAuto)).

Если объект не был найден, то работа клиента завершается ошибкой:

Рис. 17 - Сообщение о недоступном сервере RPC


Если же запись об OLE объекте была найдена в реестре, вызывается функция CoCreateInstance(), и в качестве одного из параметров ОС передает ей найденный в реестре CLSID, соответствующий имени объекта. Система обращается к серверу автоматизации. Создается фабрика класса, через интерфейс которой по данному CLSID создается экземпляр com-объекта. Компилятор генерирует код заместителя(proxy) и код заглушки(stub) на языке IDL. При нажатии на вторую кнопку связь между клиентом и сервером прекращается, объект автоматизации уничтожается.

Для взаимодействия клиента и сервера в разных адресных пространствах используются proxy и stub. Когда клиент хочет вызвать некоторый метод интерфейса, он обращается к proxy, который упаковывает параметры метода в стандартный формат для пересылки между процессами и передает запрос и параметры в процесс com-объекта (Эта процедура называется Маршаллинг). В сервере с помощью stub происходит распаковка параметров из стандартного формата и вызов метода внутри объекта (Эта процедура называется Демаршаллинг). Процедуры межпроцессовых взаимодействий осуществляются посредством ОС.

Результат работы программы:

Рис. 18 - Внешний вид приложения сервера


Увеличим длину ячеек и количество строк:


Рис. 19 - Внешний вид приложения клиента


Результат:

Рис. 20 - Внешний вид сервера после внесенных изменений

Заключение

позволяет клиенту создавать и использовать объекты, как на удаленных системах, так и на локальной. Подобно тому, как клиенты СОМ имеют прозрачный доступ к объектам в динамических библиотеках и локальных процессах, DCOM обеспечивает прозрачный доступ к объектам в удаленных процессах.

Несмотря на отдельные сложные моменты, DCOM проста для понимания. Она добавляет к знакомым основам СОМ всего 3 основных элемента: способ создания удаленного объекта, протокол вызова методов этого объекта и механизмы обеспечения безопасного доступа к нему.

В данной курсовой работе был реализован вызов удаленных процедур(RPC) по технологии DCOM, используя объектно-ориентированный язык программирования Borland Builder C++. Клиентское приложение имеет возможность запустить серверное приложение на удаленном компьютере и вызвать необходимые ему методы или установить соответствующие свойства.

Литература


1. Э. Таненбаум, М. ван Стен Распределенные системы. Принципы и парадигмы - СПб: Питер, 2002г.

. А. Олифер, В.Г. Олифер Сетевые операционные системы - СПб: Питер, 2002г.

. Дейл Роджерсон. Основы COM. M.: Издательский отдел.Русская редакция., 1997

. #"justify">Приложение


Исходные тексты программ


Сервер:

Main.h

#ifndef MainH

#define MainH

//------------------------------------------------------------------

#include <Classes.hpp>

#include <Controls.hpp>

#include <StdCtrls.hpp>

#include <Forms.hpp>

#include <ExtCtrls.hpp>

#include <ComCtrls.hpp>

//------------------------------------------------------------------TMainForm : public TForm

{

__published:// IDE-managed Components*image;

TLabel *Label3;*Label4;*Label7;

private:// User declarations:// User declarations

__fastcall TMainForm(TComponent* Owner);__fastcall Draw();__fastcall drawPos(int p,double s);

};TReostat

{:

double r;pos;nc;step;:

__fastcall TReostat(){r=0;pos=0;nc=9;step=20;};__fastcall GetPosition(){return pos;};__fastcall GetR(){return r;};__fastcall GetNC(){return nc;};__fastcall GetStep(){return step;};__fastcall SetPosition( int val ){pos = val;};__fastcall SetNC( int val ){nc = val;};__fastcall SetStep( double val ){step = val;};__fastcall SetR( double val ){r = val;};

};PACKAGE TMainForm *MainForm;

#endif.cpp

//--------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include "Main.h"

#include <math.h>

//--------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"*MainForm;

//Coil - виток проволоки реостата

//NC - количество витков

//--------------------------------------------------------------------

__fastcall TMainForm::TMainForm(TComponent* Owner)

: TForm(Owner)

{ Label3->Caption="Сопротивление реостата (Ом):";

Draw();*Reostat = new TReostat();

}

//--------------------------------------------------------------------__fastcall TMainForm::Draw()

{ TReostat *Reostat = new TReostat();->SetNC(10);

Reostat->SetPosition(4);

//начальная позиция - 30

//конечная позиция - 530

//диапазон - 500>SetStep( 500/(Reostat->GetNC()-1));*o = image->Canvas;>Brush->Color = clWhite;>FillRect( image->ClientRect );>Pen->Color = clBlack;X = 30, Y = 50, Y1 = 150;(int i=0;i<Reostat->GetNC();i++)

{>MoveTo(X,Y);>LineTo(X,Y1);(i!=(Reostat->GetNC()-1))

{>MoveTo(X,Y);>LineTo((X+Reostat->GetStep()),Y1);

}break;+=Reostat->GetStep();

}= 30;= 100;>MoveTo(X-20,Y);

o->LineTo(X,Y);>MoveTo(X+560,Y);>LineTo(X+520,Y);>LineTo(X+520,Y-80);(Reostat->GetPosition(),Reostat->GetStep());

}

//--------------------------------------------------------------------__fastcall TMainForm::drawPos( int p, double s )

{ TCanvas *o = image->Canvas;>Pen->Color = clBlack;X = 30;+=p*s;Y = 50;>MoveTo(X,Y);>LineTo(X+5,Y-20);>MoveTo(X,Y);>LineTo(X-5,Y-20);

o->LineTo(X+5,Y-20);>LineTo(X,Y);

o->MoveTo(X,Y-20);>LineTo(X,Y-30);=30;>LineTo(X+520,Y-30);

}

//--------------------------------------------------------------------.h

#ifndef MatrixH

#define MatrixH

//---------------------------------------------------------------------------

#include "RandGen.h"

class Matrix

{:();(Matrix &m);

~Matrix();

void SetSize(int m, int n);Fill(int val);FindMax();FindMin();SetElem(int i, int j, int val);GetM();GetN();GetElem(int i, int j);SetGen(RandGen * pG);FillRand();Determ();& DelLine(int k);

Matrix& DelCol(int k);:

int M;N;** A;* pGen;

};

#endif.cpp

#pragma hdrstop

#include <alloc.h>

#include "Matrix.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)::Matrix()

{= 0;(3, 3);(0);

}::Matrix(Matrix &m)

{= m.M;= m.N;= (int **) malloc(sizeof(int *) * M);(int i=0; i<M; i++)[i] = (int *) malloc(sizeof(int) * N);(int i=0; i<M; i++)

{(int j=0; j<N; j++)[i][j] = m.A[i][j];

}

}::~Matrix()

{(int i=0; i<M; i++)(A[i]);(A);

}Matrix::SetSize(int m, int n)

{= m;= n;= (int **) malloc(sizeof(int *) * M);(int i=0; i<M; i++)[i] = (int *) malloc(sizeof(int) * N);

}Matrix::Fill(int val)

{(int i=0; i<M; i++)

{(int j=0; j<N; j++)

{[i][j] = val;

}

}

}Matrix::FindMax()

{max = A[0][0];(int i=0; i<M; i++)

{(int j=0; j<N; j++)

{(A[i][j] > max)= A[i][j];

}

}max;

}Matrix::FindMin()

{min = A[0][0];(int i=0; i<M; i++)

{(int j=0; j<N; j++)

{(A[i][j] < min)= A[i][j];

}

}min;

}Matrix::SetElem(int i, int j, int val)

{[i][j] = val;

}Matrix::GetM()

{M;

}Matrix::GetN()

{N;

}Matrix::GetElem(int i, int j)

{A[i][j];

}Matrix::SetGen(RandGen * pG)

{= pG;

}Matrix::FillRand()

{(int i=0; i<M; i++)

{(int j=0; j<N; j++)

{[i][j] = pGen->Get();

}

}

}Matrix::Determ()

{

int val[16];(M != N)

{

//MessageBox("Determinant: Incorrect Matrix Size!\n");0;

}value = 0;(M)

{1: return A[0][0];2: return A[0][0]*A[1][1] - A[0][1]*A[1][0];:(int j=0; j<N; j++)

{Temp(*this);.DelLine(0);Temp.DelCol(j);(j%2 == 0)[j] = A[0][j] * Temp.Determ();[j] = -A[0][j] * Temp.Determ();

}(int j=0; j<N; j++)+= val[j];value;

}

}& Matrix::DelLine(int k)

{(k >= M)

{

//printf("DelLine: Incorrect Line Number!\n");*this;

}(A[k]);(int i = k; i<M-1; i++)[i] = A[i+1];-;*this;

}& Matrix::DelCol(int k)

{(k >= N)

{

//printf("DelCol: Incorrect Column Number!\n");*this;

}(int i = 0; i<M; i++)

{(int j = k; j<N-1; j++)[i][j] = A[i][j+1];

}-;*this;

}.h

//---------------------------------------------------------------------------

#ifndef RandGenH

#define RandGenH

//---------------------------------------------------------------------------RandGen

{:

RandGen();

~RandGen();Init();Get();

void SetInterval(int i_min, int i_max);GetMin();GetMax();:min;max;

};

#endif.cpp

#pragma hdrstop

#include <stdlib.h>

#include "RandGen.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)::RandGen()

{= 0;= 10;

}::~RandGen()

{

//TODO: Add your source code here

}RandGen::Init()

{

randomize();

}RandGen::Get()

{random(max - min) + min;

}RandGen::SetInterval(int i_min, int i_max)

{= i_min;= i_max;

}RandGen::GetMin()

{min;

}RandGen::GetMax()

{max;

}.h

#ifndef ViewH

#define ViewH

//---------------------------------------------------------------------------

#include <graphics.hpp>

#include "Matrix.h"View

{:();

~View();Draw(TCanvas * Canvas);SetMatrix(Matrix * pM);GetSizeX();GetSizeY();SetSizeX(int size){SizeX = size;}SetSizeY(int size){SizeY = size;}:SizeX;SizeY;* pMatr;

};

#endif.cpp

#pragma hdrstop

#include "View.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)::View()

{= 50;= 40;

}::~View()

{

//TODO: Add your source code here

}View::Draw(TCanvas * Canvas)

{(int i=0; i<pMatr->GetM(); i++)

{(int j=0; j<pMatr->GetN(); j++)

{>Rectangle(SizeX*j, SizeY*i, SizeX*(j+1), SizeY*(i+1));text = pMatr->GetElem(i, j);xt = SizeX*j + SizeX/2 - Canvas->TextWidth(text)/2;yt = SizeY*i + SizeY/2 - Canvas->TextHeight(text)/2;>TextOutA(xt, yt, text);

}

}

}View::SetMatrix(Matrix * pM)

{= pM;

}View::GetSizeX()

{SizeX;

}View::GetSizeY()

{SizeY;

}.h

// Event Support : TRUE

// Default ProgID : Serv.OOPAmpAuto

// Description :

/////////////////////////////////////////////////////////////////////////////ATL_NO_VTABLE TOOPAmpAutoImpl : CComObjectRootEx<CComSingleThreadModel>,CComCoClass<TOOPAmpAutoImpl, &CLSID_OOPAmpAuto>,IConnectionPointContainerImpl<TOOPAmpAutoImpl>,TEvents_OOPAmpAuto<TOOPAmpAutoImpl>, IDispatchImpl<IOOPAmpAuto, &IID_IOOPAmpAuto, &LIBID_Serv>

{:()

{

}

// Data used when registering Object

//_THREADING_MODEL(otApartment);_PROGID("Serv.OOPAmpAuto");_DESCRIPTION("");

// Function invoked to (un)register object

//HRESULT WINAPI UpdateRegistry(BOOL bRegister)

{<TOOPAmpAutoImpl> (GetObjectCLSID(), GetProgID(), GetDescription());regObj.UpdateRegistry(bRegister);

}_COM_MAP(TOOPAmpAutoImpl)_INTERFACE_ENTRY(IOOPAmpAuto)_INTERFACE_ENTRY2(IDispatch, IOOPAmpAuto)_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)_COM_MAP()_CONNECTION_POINT_MAP(TOOPAmpAutoImpl)_POINT_ENTRY(DIID_IOOPAmpAutoEvents)_CONNECTION_POINT_MAP()

// IOOPAmpAuto:TOOPAmpAutoImpl::get_Position(int* Value);TOOPAmpAutoImpl::set_Position(int Value);TOOPAmpAutoImpl::get_R(double* Value);TOOPAmpAutoImpl::set_R(double Value);TOOPAmpAutoImpl::get_NC(int* Value);TOOPAmpAutoImpl::set_NC(int Value);(get_NC(unsigned* Value));(get_Position(long* Value));(get_R(unsigned* Value));(set_NC(unsigned Value));(set_Position(long Value));(set_R(unsigned Value));

};

#endif //OOPAmpAutoImplH.cpp

// OOPAMPAUTOIMPL : Implementation of TOOPAmpAutoImpl (CoClass: OOPAmpAuto, Interface: IOOPAmpAuto)

#include <vcl.h>

#include "Main.h"

#pragma hdrstop

#include "OOPAMPAUTOIMPL.H"

// TOOPAmpAutoImplTOOPAmpAutoImpl::get_Position(int* Value)

{

{ TReostat *Reostat = new TReostat();

*Value = Reostat->GetPosition(); }(Exception &e)

{ return Error(e.Message.c_str(), IID_IOOPAmpAuto); }S_OK;

};TOOPAmpAutoImpl::set_Position(int Value)

{ try

{ TReostat *Reostat = new TReostat();>SetPosition(Value);>Draw();

}(Exception &e)

{ return Error(e.Message.c_str(), IID_IOOPAmpAuto); }S_OK;

};TOOPAmpAutoImpl::get_R(double* Value)

{ try

{ TReostat *Reostat = new TReostat();

*Value = Reostat->GetR();}(Exception &e)

{ return Error(e.Message.c_str(), IID_IOOPAmpAuto); }S_OK;

};TOOPAmpAutoImpl::set_R(double Value)

{

{ TReostat *Reostat = new TReostat();>SetR(Value);>Label4->Caption = Value;

}(Exception &e)

{ return Error(e.Message.c_str(), IID_IOOPAmpAuto); }S_OK;

};TOOPAmpAutoImpl::get_NC(int* Value)

{ try

{ TReostat *Reostat = new TReostat();

*Value = Reostat->GetNC(); }(Exception &e)

{ return Error(e.Message.c_str(), IID_IOOPAmpAuto); }S_OK;

};TOOPAmpAutoImpl::set_NC(int Value)

{ try

{ TReostat *Reostat = new TReostat();>SetNC(Value);>Draw();

}(Exception &e)

{ return Error(e.Message.c_str(), IID_IOOPAmpAuto); }S_OK;

};TOOPAmpAutoImpl::get_NC(unsigned* Value)

{

{

}(Exception &e)

{Error(e.Message.c_str(), IID_IOOPAmpAuto);

}S_OK;

};TOOPAmpAutoImpl::get_Position(long* Value)

{

{

}(Exception &e)

{Error(e.Message.c_str(), IID_IOOPAmpAuto);

}S_OK;

};TOOPAmpAutoImpl::get_R(unsigned* Value)

{

{

}(Exception &e)

{Error(e.Message.c_str(), IID_IOOPAmpAuto);

}S_OK;

};TOOPAmpAutoImpl::set_NC(unsigned Value)

{

{

}(Exception &e)

{Error(e.Message.c_str(), IID_IOOPAmpAuto);

}S_OK;

};TOOPAmpAutoImpl::set_Position(long Value)

{

{

}(Exception &e)

{Error(e.Message.c_str(), IID_IOOPAmpAuto);

}S_OK;

};TOOPAmpAutoImpl::set_R(unsigned Value)

{

{

}(Exception &e)

{Error(e.Message.c_str(), IID_IOOPAmpAuto);

}S_OK;

};

Клиент:.h*CSpinEdit2;*Button1;*GroupBox2;*Label3;*Label4;*CSpinEdit3;*CSpinEdit4;*Button2;*GroupBox3;*Label5;*Label6;*CSpinEdit5;*CSpinEdit6;*Button3;*GroupBox4;*Button4;*Button5;*Label7;*Edit1;*Label8;*CSpinEdit7;*Label9;*CSpinEdit8;*Button6;*Label10;*Edit2;*GroupBox5;*RadioButton1;*RadioButton2;*Button7;*Label11;*Button8;*Button9;*Button10;*Button11;*Edit3;*RadioButton3;__fastcall Button9Click(TObject *Sender);__fastcall Button10Click(TObject *Sender);__fastcall Button11Click(TObject *Sender);__fastcall Button1Click(TObject *Sender);__fastcall Button2Click(TObject *Sender);__fastcall Button6Click(TObject *Sender);__fastcall Button5Click(TObject *Sender);__fastcall Button4Click(TObject *Sender);__fastcall Button8Click(TObject *Sender);__fastcall Button7Click(TObject *Sender);__fastcall Button3Click(TObject *Sender);__fastcall FormCreate(TObject *Sender);__fastcall FormClose(TObject *Sender, TCloseAction &Action);:// User declarationsm_object;:// User declarations

__fastcall TForm1(TComponent* Owner);

};

//---------------------------------------------------------------------------PACKAGE TForm1 *Form1;

//---------------------------------------------------------------------------

#endif.cpp__fastcall TForm1::Button4Click(TObject *Sender)

{.OleProcedure("RandomFill");

}

//---------------------------------------------------------------------------__fastcall TForm1::Button8Click(TObject *Sender)

{value;.OleProcedure("GetElem", CSpinEdit7->Value,->Value, &value);->Text = value;

}

//---------------------------------------------------------------------------__fastcall TForm1::Button7Click(TObject *Sender)

{res;(RadioButton1->Checked).OleProcedure("FindMin", &res);if(RadioButton2->Checked).OleProcedure("FindMax", &res);if(RadioButton3->Checked).OleProcedure("FindDet", &res);->Text = res;

}

//---------------------------------------------------------------------------__fastcall TForm1::Button3Click(TObject *Sender)

{.OlePropertySet("SizeX", CSpinEdit5->Value);.OlePropertySet("SizeY", CSpinEdit6->Value);

}

//---------------------------------------------------------------------------__fastcall TForm1::FormCreate(TObject *Sender)

{lpBuffer[MAX_COMPUTERNAME_LENGTH + 1];long nSize = sizeof(lpBuffer);(lpBuffer, &nSize);text = AnsiString().sprintf("Date and time at %s is %s", lpBuffer, DateTimeToStr(Now()));

}

//---------------------------------------------------------------------------__fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)

{_object.Unbind();

}

//---------------------------------------------------------------------------



Введение Распределенные приложения обладают рядом потенциальных преимуществ по сравнению с локальными. Среди этих преимуществ - более высокая производите

Больше работ по теме:

КОНТАКТНЫЙ EMAIL: [email protected]

Скачать реферат © 2017 | Пользовательское соглашение

Скачать      Реферат

ПРОФЕССИОНАЛЬНАЯ ПОМОЩЬ СТУДЕНТАМ