Пример программы, реализующей удаленный доступ
В примере Remoting клиент обращается к активизированному сервером объекту. Сервер – это класс TcpServerChannel, использующий двоичный формат с протоколом управления передачей TCP. Канал будет использовать порт 8085. Сервер регистрирует удаленный тип, имя конечной точки для ссылки на этот объект и тип активизации. Потом сервер переходит в состояние ожидания клиентских запросов.
TcpServerChannel *chan = new TcpServerChannel(8085); ChannelServices::RegisterChannel(chan); // канал RemotingConfiguration::RegisterWellKnownServiceType( _typeof(Customers), // Клиенты "AcmeCustomer", WellKnownObjectMode::Singleton); // Единичный предмет
Сервер должен быть запущен прежде, чем клиентская программа обратится к объекту. Клиент устанавливает объект TcpClientChannel и затем присоединяется к нему.. Он определяет требуемый тип объекта и конечную точку, в которой сервер будет ожидать запросы объекта. Если нужно выполнить клиент и сервер на отдельных машинах, необходимо указать имя машины сервера для локального узла в конечной точке. В отличие от прозрачности определения места расположения в модели компонентных объектов Microsoft (СОМ), клиент должен сам определить конкретную конечную точку. Здесь нет переадресации с помощью скрытой записи в системном реестре.
TcpClientChannel *chan = new TcpClientChannel; ChannelServices::RegisterChannel(chan); // канал Customers *obj = dynamic_cast<Customers *>(// Клиенты Activator::GetObject(// Активатор _typeof(Customers), // Клиенты "tcp://localhost:8085/AcmeCustomer")); if (obj == 0) // если (obj == 0) Console::WriteLine("Could not locate server"); // ("He могу определить местонахождение сервера"); else {
Потом клиент использует заместитель, чтобы вызвать объект так, как будто это локальный экземпляр.
bool bRet = // логический (булев) RemotingServices::IsTransparentProxy(obj); ArrayList *ar; ar = obj › GetCustomer(-1); ShowCustomerArray(ar);
Чтобы выполнить программу, нужно сначала запустить сервер с одной консоли, а затем запустить клиент в другом консольном окне.
Вывод зависит от того, какой объект активизирует сервер. Если на сервере активизируется Singleton (Одноэлементное [одноточечное] множество) – объект, который может иметь состояние, то получим поведение, какого можно ожидать в случае недистанциированного объекта. Когда новый клиент добавлен, его можно обнаружить в списке, если сделать запрос обо всех существующих клиентах. Как и следовало ожидать, начальный активизирующий вызов приводит к тому, что конструктор Customers (Клиенты) вызывается один раз при каждом инициировании работы сервера, независимо от количества запусков клиентской программы.
Object reference a proxy?: True Client: AppDomain Client.exe Thread 19 Context 0 1 Rocket Squirrel rocky@frosbitefalls.com 2 Bullwinkle Moose moose@wossamotta.edu 1 Rocket Squirrel rocky@frosbitefalls.com 2 Bullwinkle Moose moose@wossamotta.edu 3 Boris Badenough boris@no-goodnicks.com
Результаты весьма отличаются от приведенных выше, если тип активизации – SingleCall, при котором для каждого вызова метода создается новый экземпляр объекта. При этом создаются четыре различных объекта. Первый объект создан при начальном активизирующем запросе. Второй создается при начальном вызове метода GetCustomer. Третий объект создается вследствие вызова RegisterCustomer. И четвертый – в результате повторного вызова метода GetCustomer. Последний созданный объект никогда не увидит нового клиента, потому что состояние не сохраняется.
Обратите внимание, что статический член nextCustld класса Customer (Клиент) обрабатывается как статический относительно новых экземпляров объектов класса Customer (Клиент), т.е. именно так, как того и следовало ожидать. Тот же программный код клиента, а результаты различные! Поскольку объект уже активизирован, при повторном выполнении клиентской программы для той же самой инициализации работы сервера, конструктор Customer (Клиент) будет вызван только трижды.
Object reference a proxy?: True Client: AppDomain Client.exe Thread 19 Context 0 3 Rocket Squirrel rocky@frosbitefalls.com 4 Bullwinkle Moose moose@wossamotta.edu 8 Rocket Squirrel rocky@frosbitefalls.com 9 Bullwinkle Moose moose@wossamotta.edu
Поскольку клиент использует заместитель, объект выполняется в рамках прикладной области сервера, но в потоке, отличном от главного потока сервера. Конструктор объекта не вызывается до первого вызова какого-нибудь метода этого объекта. В обоих случаях мы получили удаленный список массивов (ArrayList) типов, не проделывая какой-либо специальной работы, кроме указания на то, что тип может быть преобразован в последовательную форму. Именно использование метаданных значительно облегчает работу программиста.