Канал регистрируется с помощью статического метода
ChannelServices.RegisterChannel
.
Здесь представлен серверный код для регистрации каналов HTTP и TCP:
TcpChannel tcpChannel = new TcpChannel(8086);
HttpChannel httpChannel = new HttpChannel(8085);
Channel Services.RegisterChannel(tcpChannel);
СhannelServices.RegisterChannel(httpChannel);
Служебный класс
ChannelServices
можно теперь использовать для отправки синхронных и асинхронных сообщений и для отмены регистрации определенных каналов. Свойство
RegisteredChannels
возвращает массив
IChannel
всех зарегистрированных каналов. Возможно также и< пользование метода
GetChannel
для доступа к определенному каналу по его имени. С помощью
ChannelServices
пишется специальная административная утилита для управления каналами. Вот небольшой пример показывающий как можно остановить режим прослушивания канала:
. На серверной стороне он используется для регистрации типов удаленных объектов активированных на сервере объектов и для маршализации удаленных объектов в ссылочный класс маршализованного объекта
ObjRef
.
ObjRef
является сериализуемым представлением объекта, которое было послано по линии связи. На клиентской стороне работает
RemotingServices
, демаршализуя удаленный объект, чтобы создать прокси из объектной ссылки.
Вот серверный код для регистрации хорошо известного типа удаленного объекта в
определяет тип удаленного объекта. Второй аргумент —
Hi
является универсальным идентификатором ресурса удаленного объекта, который используется клиентом для доступа к удаленному объекту. Последний аргумент — режим удаленного объекта. Режим может быть значением перечисления
WellKhownObjectMode
:
SingleCall
или
Singleton
.
□
SingleCall
означает, что объект не сохраняет состояние. Для каждого вызова удаленного объекта создается новый экземпляр. Объект
. Это очень эффективно для сервера, так как получается, что не требуется поддерживать ресурсы может быть для тысяч клиентов.
□ С помощью режима Singleton объект совместно используется всеми клиентами сервера. Такие объектные типы могут применяться, если желательно предоставить доступ к некоторым данным всем клиентам. Это не должно быть проблемой для читаемых данных, но для данных чтения-записи необходимо знать о вопросах блокировки и масштабируемости. Объект
. Необходимо убедиться, что данные не могут быть повреждены, когда клиенты получают доступ одновременно, но нужно и проверять, что блокирование сделано достаточно эффективно для достижения требуемой масштабируемости.
Сервер для активизированных клиентом объектов
Если удаленный объект должен хранить состояние для определенного клиента, то можно использовать активизированные клиентом объекты. В следующем разделе будут рассмотрены возможности клиентской стороны. В частности, как вызывать объекты, активизированные сервером, и объекты, активизированные клиентом. На серверной стороне активизированные клиентом объекты должны регистрироваться по-другому, чем объекты, активизированные сервером.
Вместо вызова
RemotingConfiguration.RegisterWellKnownType
необходимо вызвать
RemotingServices.RegisterActivatedServiceType
. С помощью этого метода определяются только типы, но не URI. Причина этого заключается
в том, что для активированных клиентом объектов создаются экземпляры различных объектных типов с помощью одного URI. URI для всех активированных клиентом объектов должен быть определен с помощью
Для клиентов возможно использование и создание удаленных объектов с помощью класса
Activator
. Мы можем получить прокси для активированного сервером или хорошо известного удаленного объекта с помощью метода
GetObject
. Метод
CreateInstance
возвращает прокси для активированного клиентом удаленного объекта.
Вместо класса
Activator
для активации удаленных объектов используется также оператор new. Чтобы сделать это, удаленный объект должен конфигурироваться внутри клиента с помощью класса
RemotingConfiguration
.
URL-приложения
Во всех сценариях активации необходимо определять URL удаленного объекта. Этот URL является тем же самым, что и в браузере Web. Первая часть определяет протокол, за которым следует имя сервера или адрес IP, номер порта и URI, определенный при регистрации удаленного объекта на сервере в таком виде:
protocol://server:port/URI
Мы все время используем в нашем коде два примера URL: определяем протокол
http
и
tcp
, имя сервера
localhost
, номер порта 8085 и 8086, и
URI
как
Hi
, что дает нам запись:
http://localhost:8085/Hi
tcp://localhost:8086/Hi
Активация хорошо известных объектов
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
/// ...
TcpClientChannel channel = new TcpClientChannel;
ChannelServices.RegisterChannel(channel);
Hello obj = (Hello)Activator.GetObject(
typeof(Hello), "tcp://localhost:8086/Hi");
GetObject
является статическим методом класса
System.Activator
, который вызывает метод
RemotingServices.Connect
для возврата объекта прокси удаленному объекту. Первый аргумент определяет тип удаленного объекта. Прокси реализует все открытые и защищенные методы и свойства, так что клиент может вызывать эти методы так же, как для реального объекта. Второй аргумент является URL удаленного объекта. Здесь используется строка
tcp://localhost:8086/Hello
, где
tcp
— протокол,
localhost:8086
— имя хоста и номер порта и, наконец,
Hello
— это URI объекта, который был определен с помощью
Если вы предпочитаете задать просто оператор new для активизации хорошо известных удаленных объектов, то удаленный объект можно зарегистрировать на клиенте с помощью все того же
RemotingConfiguration.RegisterWellKnownClientType
. Здесь понадобятся похожие аргументы: тип удаленного объекта и URI. Теперь можно использовать оператор new, который на самом деле не создает новый удаленный объект, а возвращает прокси аналогично
Activator.GetObject
. Если удаленный объект регистрируется с флажком
WellKnownObjectMode.SingleCall
, правило остается тем же самым: удаленный объект создается с каждым вызовом метода: