Главa 23
В главе 17 были рассмотрены службы Web, которые позволяют вызывать объекты на удаленном сервере. Использование сервера Web и протокола SOAP не всегда достаточно эффективно для приложений интранет. Протокол SOAP означает большие накладные расходы при пересылке большого объема данных. Для быстрых решений интранет можно использовать просто сокеты, как это делалось в предыдущей главе. В «старом мире», как известно, программы писали с использованием DCOM. С помощью DCOM можно вызывать методы на объектах, выполняющихся на сервере. Программная модель всегда является одной и той же, если объекты применяются на сервере или на клиенте.
Без DCOM мы вынуждены иметь дело с портами и сокетами, уделяя внимание целевым платформам в связи с возможным различным представлением данных, и создавать специальные протоколы, в которых сообщения посылаются сокету, чтобы, в конце концов, вызвать некоторые методы. DCOM обрабатывает все эти вопросы для программиста.
Заменой DCOM является .NET Remoting. В противоположность DCOM .NET Remoting может использоваться также в решениях Интернета, а для них DCOM недостаточно гибок и эффективен. С помощью .NET Remoting можно адаптировать и расширить любую часть архитектуры, поэтому подходит практически для любого удаленного сценария. В этой главе будут рассмотрены:
□ Архитектура .NET Remoting
□ Каналы, сообщения, приемники
□ Создание клиентов и серверов
□ Удаленные свойства с конфигурационными файлами
□ Возможности расширения рабочей среды
□ Использование возможностей удаленного управления в приложениях ASP.NET
Прежде всего выясним, что такое .NET Remoting.
Что такое .NET Remoting
Два выражения могут описать .NET Remoting: Web Services Anywhere и CLR Object Remoting. Рассмотрим, что это означает.
Web Services Anywhere
Выражение Web Services Anywhere используется в .NET Remoting и означает, что с помощью .NET Remoting службы Web могут применяться в любом приложении с помощью любого транспорта, используя какое угодно кодирование полезной нагрузки. .NET Remoting является предельно гибкой архитектурой.
Совместное использование SOAP и HTTP — только способ вызова удаленных объектов. Транспортный канал является подключаемым и может заменяться. Мы получаем каналы HTTP и TCP, представленные классами
Кодирование полезной нагрузки также можно заменить. Компания Microsoft предоставляет SOAP и механизмы двоичного кодирования. Можно использовать средство форматирования (форматтер) SOAP с помощью канала НТTР, но и использовать HTTP, применяя двоичный форматтер. Конечно оба эти форматтера можно использоватъ также с каналом TCP.
.NET Remoting не только делает возможным использование служб Web в каждом приложении .NET, но позволяет также предложить возможности службы Web в каждом приложении. Не имеет значения, создается ли консольное приложение или приложение для Windows, Windows Service или компонент COM+ — службы Web могут использоваться везде.
Термин подключаемый (pluggable) часто используется в .NET Remoting.
Подключаемый означает, что определенная часть проекта разработана так, что она может заменяться специальной реализацией.
CLR Object Remoting
CLR Object Remoting везде располагается поверх служб Web. CLR Object Remoting облегчает использование служб Web. Все конструкции языка, такие как конструкторы, делегаты, интерфейсы, методы, свойства и поля, могут использоваться с удаленными объектами. CLR Object Remoting имеет дело с активацией, распределенной идентификацией, временем жизни и контекстами вызова.
Обзор .NET Remoting
.NET Remoting может использоваться для доступа к объектам в домене другого приложения независимо от того, находятся ли два объекта внутри одного процесса, в разных процессах или на разных системах.
Удаленные сборки можно сконфигурировать для локальной работы в домене приложения или как часть удаленного приложения. Если сборка является частью удаленного приложения, то клиент получает для общения прокси вместо реального объекта. Прокси посылает сообщение в канал.
Приложения .NET работают внутри домена приложения. Домен приложения можно рассматривать как подпроцесс внутри процесса, Традиционно процессы используются как изолирующая граница. Приложение, выполняющееся в одном процессе, не может получить доступ и разрушить память в другом процессе. Чтобы приложения общались друг с другом, требуется межпроцессная коммуникация. При использовании .NET домен приложения выступает новой границей безопасности внутри процесса, так как код CIL является проверяемым и обеспечивает безопасность типов данных. Различные приложения могут выполняться внутри одного процесса, но внутри различных доменов приложений. Объекты внутри одного домена приложений могут взаимодействовать напрямую. Чтобы получить доступ к объектам в другом домене приложений, требуется прокси.
Больше о доменах приложений можно узнать в главе 8.
Прежде чем перейти к внутренней функциональности .NET Remoting, давайте рассмотрим основные элементы архитектуры:
□ Удаленный объект является объектом, который выполняется на сервере. Клиент не вызывает методы на этом объекте напрямую, а использует для этого прокси. С помощью .NET легко отличить удаленные объекты от локальных: каждый класс, производный из
□ Канал используется для коммуникации между клиентом и сервером. Существует клиентская и серверная часть канала. С помощью .NET Framework мы получаем два типа каналов, которые общаются через TCP или HTTP. Можно также создать специальный канал, который поддерживает связь с помощью другого протокола.
□ Сообщения посылаются в канал. Они создаются для коммуникации между клиентом и сервером и хранят информацию об удаленных объектах, именах вызванных методов и всех аргументах.
□ Форматтер определяет, как сообщения передаются в канал. Вместе с .NET Framework мы получаем форматтеры SOAP и двоичный. Форматтер SOAP можно использовать для коммуникации со службами Web, которые не основываются на .NET Framework. Двоичные форматтеры действуют значительно быстрее и могут эффективно использоваться в среде интранет. Конечно, имеется возможность создать специальный форматтер.
□ Провайдер форматтера используется для соединения форматтера с каналом. Создавая канал, можно выбрать провайдер форматтера, и этот выбор в свою очередь, определяет форматтер, который будет использоваться для передачи данных в канал.
□ Клиент вызывает методы на прокси, а не на удаленном объекте. Существует два типа прокси: прозрачный прокси и реальный прокси. Прозрачный прокси выглядит для клиента как удаленный объект. Клиент может вызывать методы, реализуемые удаленным объектом на прозрачном прокси. В свою очередь, прозрачный прокси вызывает метод
□ Приемник сообщений является объектом-перехватчиком. Такие перехватчики имеются как на клиенте, так и на сервере. Приемник ассоциируется с каналом. Реальный прокси использует его для передачи сообщения в канал, поэтому приемник осуществляет некоторый перехват, прежде чем сообщения попадают в канал.
□ Клиент может использовать активатор для создания удаленного объекта на сервере или для получения прокси активированного сервером объекта.
Чтобы получить представление о функциональности, давайте рассмотрим концептуально, как элементы сочетаются друг с другом.
Когда клиент вызывает методы на удаленном объекте, он на самом деле вызывает вместо этого методы на прозрачном прокси. Прозрачный прокси выглядит как реальный объект, он реализует открытые методы реального объекта. Прозрачный прокси узнает об открытых методах, используя механизм отражения для считывания метаданных из сборки.
Прозрачный прокси, в свою очередь, вызывает реальный прокси. Реальный прокси отвечает за отправку сообщения в канал. Реальный прокси является подключаемым, можно заменить его с помощью специальной реализации, которая применяется для записи журнала для другого способа поиска канала и т.д. Используемая по умолчанию реализация реального прокси находит совокупность (или цепочку) уполномоченных приемников и передает сообщение в первый уполномоченный приемник. Уполномоченный приемник может перехватить и изменить сообщение. Примерами таких приемников являются приемники отладки, системы безопасности, синхронизации. Последний уполномоченный приемник досылает сообщение в канал. Как сообщение передается по линиям связи, зависит от форматтера. Ранее уже упоминалось, что имеются SOAP и двоичный форматтеры, которые также являются подключаемыми. Канал отвечает либо за соединение с принимающим сокетом на сервере, либо за отправку форматированных данных. Со специальным каналом можно производить различные действия, необходимые для передачи данных на другую сторону.
Продолжим рассмотрение на серверной стороне. Канал получает форматированные сообщения от клиента и использует форматтер для демаршализации данных SOAP или двоичных данных в сообщениях. Затем канал вызывает приемники серверного контекста, которые, в свою очередь, являются цепочкой приемников, где последний приемник в цепочке продолжает вызов в цепочке объектов приемников контекста. Последний объект приемника контекста вызывает метод в удаленном объекте. Объектные приемники соответствуют объекту, серверные приемники контекста соответствуют контексту. Для доступа к ряду объектных приемников может использоваться единственный приемник контекста
.NET Remoting легко модифицируется: можно заменить реальный прокси, добавить объекты приемника, заменить форматтер и канал. Конечно, можно также использовать все, что уже предоставлено. При этом необходимо отметить, что связанные с прохождением через эти слои накладные расходы можно считать почти отсутствующими. Если вы добавите собственную функциональность, накладные расходы будут зависеть от нее.
Контексты
Прежде чем рассматривать возможности .NET Remoting для создания серверов и клиентов, которые общаются в сети, давайте рассмотрим те случаи, когда внутри домена приложения требуется канал, осуществляющий вызов объектов через контексты.
При создании компонентов COM+ использовались контексты COM+. Контексты в .NET являются очень похожими. Как уже было сказано, один процесс может иметь несколько доменов приложений. Домен приложения является чем-то типа подпроцесса с границами безопасности и может иметь различные контексты. Контекст используется для группирования объектов с аналогичными требованиями выполнения. Контексты состоят из множества свойств и используются для перехватывания: когда к ограниченному контекстом объекту обращаются из другого контекста, перехватчик может сделать некоторую работу, прежде чем вызов достигнет объекта.
Класс, который выводится из
Чтобы понять контексты, необходимо знать некоторые термины:
□ Создание домена приложения приводит к возникновению контекста по умолчанию в этом домене. Если вы возьмете экземпляр нового объекта, которому требуются другие свойства контекста, в соответствии с ними создастся новый контекст.
□ Атрибуты контекста могут присваиваться классам, производным из
□ Атрибуты контекста определяют свойства контекста, необходимые объекту. Класс свойства контекста реализует интерфейс
□ Приемник сообщений является перехватчиком вызова метода. При этом свойства помогают работе приемников сообщений.
Активизация
Новый контекст создается, если экземпляру создаваемого класса требуется контекст, отличный от вызывающего контекста. Классы атрибутов, которые ассоциируются с целевым классом, запрашиваются в том случае, если все свойства текущего контекста в порядке. Если один из этих классов атрибутов присылает
Атрибуты и свойства
Класс атрибута контекста является прежде всего атрибутом. Более подробно можно прочитать об этом в главе 6. Классы атрибутов контекста должны реализовать интерфейс
В .NET Framework содержатся два класса атрибутов контекста:
С помощью этих атрибутов в конструкторе задаются четыре значения:
Коммуникация между контекстами
Как же происходит коммуникация между контекстами? Клиент использует вместо реального объекта прокси. Оно создает сообщение, которое передается в канал, и приемники могут выполнить перехват. Тот же самый механизм используется для коммуникации между различными доменами приложения или различными системами. Канал TCP или HTTP не требуется для коммуникации между контекстами, но канал здесь, конечно же, есть. Класс
Удаленные объекты, клиенты и серверы
Прежде чем перейти к рассмотрению деталей архитектуры .NET Remoting, давайте рассмотрим кратко удаленный объект и очень маленькое простое клиентское серверное приложение, которое использует этот удаленный объект. Затем мы обсудим более подробно все необходимые шаги и параметры.
Реализуемый удаленный объект называется
Удаленные объекты
Удаленные объекты требуются для распределенного вычисления. Объект, вызываемый удаленно с другой системы, выводится из объектов
Удаленный объект имеет распределенную идентичность. В связи с этим ссылка на объект может передаваться другим клиентам, и они также будут получать доступ к тому же объекту. Прокси знает об идентичности удаленного объекта.
Чтобы увидеть .NET Remoting в действии, создается простая библиотека классов для удаленного объекта. Класс
Для того чтобы легко различать в последующих разделах сборку и класс, дадим им различные имена аргументов, которые используют вызовы метода. Присвоим сборке имя
Что такое контекст в c
C# для профессионалов
Для кого предназначена эта книга
Основные темы книги
Платформа .NET предлагает новую среду, в которой можно разрабатывать практически любое приложение, действующее под управлением Windows, а язык C# — новый язык программирования, созданный специально для работы с .NET.
В этой книге представлены все основные концепции языка C# и платформы .NET. Полностью описывается синтаксис C#, приводятся примеры построения различных типов приложений с использованием C# — создание приложений и служб Windows, приложений и служб WWW при помощи ASP.NET, а также элементов управления Windows и WWW Рассматриваются общие библиотеки классов .NET, в частности, доступ к данным с помощью ADO.NET и доступ к службе Active Directory с применением классов DirectoryServices.
Эта книга предназначена для опытных разработчиков, возможно, имеющих опыт программирования на VB, C++ или Java, но не использовавших ранее в своей работе язык C# и платформу .NET. Программистам, применяющим современные технологии, книга даст полное представление о том, как писать программы на C# для платформы .NET.
• Все особенности языка C#
• C# и объектно-ориентированное программирование
• Приложения и службы Windows
• Создание web-страниц и web-служб с помощью ASP NET
• Доступ к данным при помощи ADO NET
• Создание распределённых приложений с помощью NET Remoting
• Интеграция с COM, COM+ и службой Active Directory
Книга: C# для профессионалов. Том II
Контексты
Прежде чем рассматривать возможности .NET Remoting для создания серверов и клиентов, которые общаются в сети, давайте рассмотрим те случаи, когда внутри домена приложения требуется канал, осуществляющий вызов объектов через контексты.
При создании компонентов COM+ использовались контексты COM+. Контексты в .NET являются очень похожими. Как уже было сказано, один процесс может иметь несколько доменов приложений. Домен приложения является чем-то типа подпроцесса с границами безопасности и может иметь различные контексты. Контекст используется для группирования объектов с аналогичными требованиями выполнения. Контексты состоят из множества свойств и используются для перехватывания: когда к ограниченному контекстом объекту обращаются из другого контекста, перехватчик может сделать некоторую работу, прежде чем вызов достигнет объекта.
Класс, который выводится из MarsnalByRefObject , ограничен доменом приложения. Вне домена приложения требуется прокси для доступа к объекту. Класс, который выводится из ContextBoundObject ограничен контекстом. Вне контекста для доступа к объекту требуется прокси. Ограниченные контекстом объекты могут иметь атрибуты контекста, объект без таких атрибутов создается в контексте создателя. Ограниченный контекстом объект с атрибутами контекста создается в новом контексте или в контексте создателя, если атрибуты являются совместимыми
Чтобы понять контексты, необходимо знать некоторые термины:
? Создание домена приложения приводит к возникновению контекста по умолчанию в этом домене. Если вы возьмете экземпляр нового объекта, которому требуются другие свойства контекста, в соответствии с ними создастся новый контекст.
? Атрибуты контекста могут присваиваться классам, производным из ContextBoundObject . Можно создать класс специального атрибута, реализуя интерфейс IContextAttribute . .NET Framework имеет два класса атрибутов контекста: SynchronizationAttribute и ThreadAffinityAttribute .
? Атрибуты контекста определяют свойства контекста, необходимые объекту. Класс свойства контекста реализует интерфейс IContextProperty . Активные свойства предоставляют приемники сообщений в цепочку вызовов. Класс ContextAttribute , который может использоваться как базовый для специальных атрибутов, реализует как IContextProperty , так и IContextAttribute .
? Приемник сообщений является перехватчиком вызова метода. При этом свойства помогают работе приемников сообщений.
Using »Context Types» in C++
This paper covers the use of type-based contexts in C++. It is targetted at intermediate-to-advanced C++ programmers.
The entire content of this article is released into the Public Domain.
Most programmers are familiar with the concept of resource handles. To recap: what is a resource handle? It is a unique identifier which identifies some type of resource within a system. The most common example is probably C’s classic file handles, which one uses to pass to functions like fclose() , so that fclose() knows which file it is really supposed to close. Handles come in a variety of flavours, but the are invariably used to define the context within which a given set of operations is performed. e.g., fclose(myhandle) instructs fclose() to only close the file associated with myhandle, and not another file.
This paper takes the concept of resource handles a step further, defining »type handles», or what we will refer to as Context Types. In short, a context type is an arbitrary type which is used to limit certain operations to a scope — the scope of the given context. Clear as mud? The rest of this paper will try to make clear what exactly context types are, how to implement them, and how they can be used to add flexibility to some otherwise-inflexible code.
C++’s template facilities offer a different type of handle, vaguely related to classic resource handles but based, instead of on runtime-mutable values, on types .
Jumping right in. here we show a trivial example of how type-based contexts can be used to genericize a very simple function. Consider the following function, who’s sole purpose is to dole out a new number each time it is called:
- Most obviously, the calling syntax of our function now changes from next_id() to next_id<T>() .
- We no longer have a single next_id() function, but, as Alexandrescu has put it, a family of next_id() functions.
- Every time this function is called with the same context a new number will be generated. That is, calls to next_id<X>() and next_id<Y>() may very well generate identical values, but call calls to next_id<X>() will get unique values (until size_t overflows, obviously).
- More subtley, ContextType is never instantiated. This means that we can pass arbitrarily large types as a context without any worries about using up system resources or violating constraints such as the Singleton-ness of a given ContextType.
- i have never seen this approach used outside of my own projects.
- i get a tremendous amount of use out of this approach. So much so that i believe other programmers could get some use out of it.
The above simple example only touches on the potential uses of context types. We’ll spend the rest of the paper trying to convince you that context types are useful in a variety of . well, contexts .
We said above that context types are conceptually similar to resource handles. How is that so? Consider: when calling next_id() with different context types we are essentially giving the function a different resource handle, i.e. a different context in which to perform it’s work. In doing so we assure that next_id<X>() and next_id<Y>() do not interfere with each other.
Let’s consider this classic example of implementing what are often dubbed Meyers Singletons, after the programming god Scott Meyers, who reportedly first published this approach:
Что такое контекст в c
На этом шаге мы рассмотрим строение и использование объекта локального контекста .
Локальный контекст C++ представляет собой неизменяемый контейнер для фацетов. Класс locale определяется в заголовочном файле <locale> следующим образом:
У локальных контекстов есть одна специфическая особенность — механизм обращения к объектам фацетов, хранящимся в контейнере. Обращение к фацету локального контекста производится по типу этого фацета, который интерпретируется как индекс. Поскольку фацеты обладают разными интерфейсами и предназначаются для разных целей, желательно, чтобы функции доступа к локальным контекстам возвращали тип, соответствующий индексу; именно это и происходит при «индексировании» по типу фацета. Другое достоинство этого механизма состоит в том, что интерфейс безопасен по отношению к типам.
Объекты локальных контекстов неизменны. Это означает, что фацеты, хранящиеся в локальных контекстах, невозможно модифицировать (кроме присваивания локальных контекстов). Модификации локальных контекстов создаются посредством объединения существующих контекстов и фацетов с формированием нового контекста. В таблице 1 перечислены конструкторы локальных контекстов.
Выражение | Описание |
---|---|
locale() | Создает копию текущего локального контекста, назначенного глобально |
locale(name) | Создает объект локального контекста для заданного имени |
locale(loc) | Создает копию локального контекста lос |
locale(loc1, loc2, cat) | Создает копию локального контекста loc1 , в которой все фацеты из категории cat заменяются фацетами локального контекста loc2 |
locale(loc, name, cat) | Эквивалент locale(loc, locale(name), cat) |
locale(loc,fp) | Создает копию локального контекста lос и устанавливает фацет, на который ссылается указатель fp |
loc1 = loc2 | Присваивает локальный контекст lос2 объекту loc1 |
loc1.template combine<F>(loc2) | Создает копию локального контекста loc1 , в которой фацет типа F берется из lос2 |
Почти все конструкторы создают копию другого объекта локального контекста. Простое копирование объекта считается относительно дешевой операцией. Фактически оно сводится к заданию указателя и увеличению счетчика ссылок. Создание модифицированного локального контекста обходится дороже, поскольку при этом приходится изменять счетчики ссылок для всех фацетов, хранящихся в локальном контексте. Хотя стандарт не дает гарантий относительно эффективности этой операции, весьма вероятно, что во всех реализациях копирование локальных контекстов будет производиться достаточно эффективно.
Два конструктора из таблицы 1 получают имена локальных контекстов. Передаваемые имена не стандартизированы (кроме имени С ). Однако стандарт требует, чтобы в документации, прилагаемой к стандартной библиотеке C++ , были перечислены допустимые имена. Предполагается, что большинство реализаций поддерживает имена, представленные на 530 шаге.
Функцию combine() стоит пояснить подробнее, поскольку в ней используется возможность, относительно недавно реализованная в компиляторах. Она представляет собой шаблонную функцию с явно заданным аргументом. Это означает, что тип аргумента шаблона не определяется по значению аргумента, поскольку такого значения попросту нет. Вместо этого аргумент шаблона (в данном случае — тип F ) задается явно.
В двух функциях для обращения к фацетам объекта локального контекста используется одинаковая методика (таблица 2). Однако эти две функции являются глобальными шаблонными функциями, поэтому уродливый синтаксис с ключевым словом template становится излишним.
Выражение | Описание |
---|---|
has_facet<F>(loc) | Возвращает true , если локальный контекст lос содержит фацет типа F |
use_facet<F>(loc) | Возвращает ссылку на фацет типа F , хранящийся в локальном контексте lос |
Функция use_facet() возвращает ссылку на фацет. Тип ссылки соответствует типу, переданному явно в аргументе шаблона. Если локальный контекст, переданный в аргументе, не содержит соответствующего фацета, функция генерирует исключение bad_cast . Чтобы узнать, присутствует ли в заданном локальном контексте некоторый фацет, воспользуйтесь функцией has_facet() .
Остальные операции локальных контекстов перечислены в таблице 3. Имя локального контекста поддерживается в том случае, если контекст был сконструирован по заданному имени или одному (или нескольким) именованным локальным контекстам. Однако и в этом случае стандарт не дает гарантий относительно построения имени, полученного при объединении двух локальных контекстов. Два локальных контекста считаются идентичными, если один из них является копией другого или если оба локальных контекста имеют одинаковые имена. Было бы естественно считать, что два объекта идентичны, если один из них является копией другого. Но что делать с именами? Предполагается, что имя локального контекста отражает имена, используемые для конструирования именованных фацетов. Например, имя локального контекста может быть сконструировано объединением имен фацетов в определенном порядке, разделенных заданными символами. Вероятно, такая схема позволит определить идентичность двух объектов локального контекста, если они были сконструированы посредством объединения одних и тех же именованных фацетов. Иначе говоря, стандарт требует, чтобы два локальных контекста, содержащих одинаковые именованные фацеты, считались идентичными.
Выражение | Описание |
---|---|
loc.name() | Возвращает имя локального контекста loc в виде string |
loc1 == lос2 | Возвращает true , если локальные контексты loc1 и lос2 идентичны |
loc1 != lос2 | Возвращает true, если локальные контексты loc1 и lос2 не идентичны |
loc(str1,str2) | Возвращает логический признак сравнения строк str1 и str2 в порядковом отношении (то есть проверяет, что str1 меньше str2 ) |
locale::classic() | Возвращает locale(«C») |
locale::global(loc) | Назначает локальный контекст loc как глобальный и возвращает предыдущий глобально назначенный локальный контекст |
Оператор () позволяет использовать объект локального контекста для сравнения строк. При этом строки, переданные в аргументах, сравниваются в порядковом отношении, и задействуется фацет collate . Иначе говоря, фацет collate проверяет, будет ли одна строка меньше другой по критериям объекта локального контекста. Такое поведение типично для объектов функций STL , поэтому объект локального контекста может использоваться в качестве критерия сортировки для алгоритмов STL , работающих со строками. Например, сортировка вектора по правилам немецкого локального контекста выполняется следующим образом: