Пользовательские обновления потоков

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

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

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

Принципы работы обновления потока

Имеется четыре компонента процесса обновления потока.

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

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

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

  4. Элемент привязки обновления потока добавляется в привязки службы и клиента и создает поставщика во время выполнения.

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

Реализация обновления потока

Windows Communication Foundation (WCF) предоставляет четыре abstract класса, которые можно реализовать:

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

  1. Создайте класс, реализующий перехватчик StreamUpgradeInitiator.

    1. Переопределите метод InitiateUpgrade, чтобы он принимал обновляемый поток и возвращал обновленный поток. Этот метод работает синхронно; имеются аналогичные методы для асинхронной инициации обновления.

    2. Переопределите метод GetNextUpgrade, чтобы он проверял на необходимость дополнительных обновлений.

  2. Создайте класс, реализующий перехватчик StreamUpgradeAcceptor.

    1. Переопределите метод AcceptUpgrade, чтобы он принимал обновляемый поток и возвращал обновленный поток. Этот метод работает синхронно; имеются аналогичные методы для асинхронного принятия обновления.

    2. Переопределите метод CanUpgrade, чтобы он проверял, поддерживается ли запрошенное обновление текущим акцептором обновления в данной точке процесса обновления.

  3. Создайте класс, реализующий StreamUpgradeProvider. Переопределите методы CreateUpgradeAcceptor и CreateUpgradeInitiator, чтобы они возвращали экземпляры акцептора и инициатора, определенные на шагах 2 и 1.

  4. Создайте класс, реализующий перехватчик StreamUpgradeBindingElement.

    1. Переопределите метод BuildClientStreamUpgradeProvider клиента и метод BuildServerStreamUpgradeProvider службы.

    2. Переопределите метод BuildChannelFactory клиента и метод BuildChannelListener службы, чтобы добавлять в свойство BindingParameters элемент привязки обновления.

  5. Добавьте новый элемент привязки обновления потока в привязки на клиентском и серверном компьютерах.

Обновления системы безопасности

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

WCF уже предоставляет два элемента привязки для обновления безопасности потока. Конфигурация безопасности транспортного уровня инкапсулируется в элементах WindowsStreamSecurityBindingElement и SslStreamSecurityBindingElement, которые можно настроить и добавить в пользовательскую привязку. Эти элементы привязки расширяют класс StreamUpgradeBindingElement, создающий поставщики обновления потока клиента и сервера. У этих элементов привязки имеются методы, создающие специальные классы поставщиков обновления системы безопасности потоков, которые не являются public, поэтому в этих двух случаях достаточно просто добавить элемент привязки в привязку.

Для сценариев обеспечения безопасности, не реализуемых с помощью описанных выше двух элементов привязки, от вышеупомянутых базовых классов инициатора, акцептора и поставщика наследуются три класса abstract, связанных с обеспечением безопасности:

  1. System.ServiceModel.Channels.StreamSecurityUpgradeInitiator

  2. System.ServiceModel.Channels.StreamSecurityUpgradeAcceptor

  3. System.ServiceModel.Channels.StreamSecurityUpgradeProvider

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

Несколько обновлений

Чтобы создать дополнительные запросы на обновление, повторите описанный выше процесс: создайте дополнительные расширения поставщика StreamUpgradeProvider и элементы привязки. Добавьте в привязку элементы привязки. Дополнительные элементы привязки обрабатываться последовательно, начиная с первого элемента привязки, добавленного в привязку. В методах BuildChannelFactory и BuildChannelListener каждый поставщик обновления может определять, как расположить себя относительно существующих параметров привязки обновления. В этом случае он должен заменить существующий параметр привязки обновления на новый составной параметр привязки обновления.

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

  1. На основе класса StreamSecurityUpgradeProvider создайте класс поставщика, который создает инициатор и акцептор.

  2. Создайте подкласс StreamSecurityUpgradeInitiator, переопределив метод GetNextUpgrade, чтобы он возвращал типы содержимого для потока сжатия и потока защиты в нужном порядке.

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

  4. Поток будет обновляться после каждого вызова методов GetNextUpgrade и CanUpgrade.

См. также