Интернет-журнал "Домашняя лаборатория", 2007 №6
Шрифт:
}
}
}
Клиент
//МуАрр. сs
using System; using MyServer;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
public class MyApp {
public static void Main {
HttpChannel с = new HttpChannel;
ChannelServices.RegisterChannel(c);
Account a = (Account)Activator.GetObject (
typeof(Account), "http://localhost:8080/Account",
WellKnownObjectMode.Singleton);
a. Add(5);
Console.WriteLine("Total = {0}", a.Total);
Console.WriteLine("Client AppDomain = {0}",
AppDomain.CurrentDomain.FriendlyName);
}
}
Для
System.Runtime.Remoting,
System.Runtime.Remoting.Channels,
System.Runtime.Remoting.Channels.Http.
Последнее пространство имен необходимо для работы с каналом, использующим http. Есть возможность работы с tcp каналом (что в несколько раз быстрее), но http канал по умолчанию передает сообщения по протоколу SOAP в стандартизованном XML формате, a tcp по умолчанию передает SOAP сообщения в нестандартизованном бинарном формате. Иными словами, при использовании html канала потенциальный клиент может вообще не принадлежать миру .NET и платформе Windows.
Необходимо обратить внимание на то, что класс Account теперь наследует классу MarshalByRefObject. Все объекты в .NET делятся на три типа:
1. передаваемые по ссылке
2. передаваемые по значению
3. не передаваемые за пределы своего домена приложения
Наш класс должен быть передаваем по ссылке. Это обеспечивается тем, что он наследует классу MarshalByRefObject. При работе с таким объектом клиент реально работает не с самим объектом, а с его прокси. Сам же объект формируется удаленно.
Наш удаленный объект должен жить в некотором приложении. Здесь мы описываем консольное приложение, функция Main (в коде сервера) — его точка входа.
В данном приложении формируется объект — http-канал (с указанием произвольного номера порта) и этот канал регистрируется в системе Remoting.
После этого в этой же системе регистрируется класс, к которому будет обеспечен доступ удаленных клиентов. Задается его тип, его URI — определяемый разработчиком идентификатор, и режим работы объекта. В данном случае это Singleton. Это означает, что такой объект создается после получения первого запроса от какого-либо клиента и далее живет (сохраняя состояние), отвечая на запросы как этого, так и других объектов.
После запуска серверного приложения на консоль сервера выдается уведомление о том, что сервер готов к работе. С этого момента сервер ожидает получения сообщений по каналу http на порт 8080. Остановить работу сервера можно нажав на клавишу <Enter>.
Теперь обратимся к клиенту. Он регистрирует один из каналов, зарегистрированных сервером (но не указывает номер порта).
Метод Activator.Getobject возвращает ссылку на прокси, сам же объект при этом не создается. Если он не был создан ранее, то он будет создан при получении первого запроса от какого-либо клиента. Среди параметров задаются тип компонента, путь к нему и режим его работы. Все остальное не изменилось по сравнению с клиентом, предназначенным для работы с сервером в домене клиентского приложения.
Теперь рассмотрим результаты работы нашего приложения. В отдельном консольном окне компилируем сервер (создаем сборку типа ехе) и запускаем его. В другом консольном окне компилируем клиента, задавая ссылку на копию серверной сборки, размещенной в каталоге клиента. Запускаем клиента два раза и видим, что сумма на счете накапливается. Кроме того видим, что сервер и клиент выполняются в различных доменах приложения.
Консоль сервера
>csc /t: exe MyServer.cs
>MyServer.ехе
Server is listening
Server AppDomain = MyServer.exe
Server AppDomain = MyServer.exe
Bye
>
Консоль клиента
>csc /r: MyServer\MyServer.ехе МуАрр. cs
>MyApp.ехе
Total = 5
Client AppDomain = MyApp.exe
>MyApp.ехе
Total = 10
Client AppDomain = MyApp.exe
>
Несколько комментариев, касающихся удаленных компонентов.
В.NET определены три типа режимов работы удаленных объектов:
1. SingleCall
Удаленный объект активируется на стороне сервера только при получении вызова какого-либо его метода от клиента и по выполнении этого метода сразу же уничтожается.
2. Singleton
Удаленный объект совместно используется несколькими клиентами, сохраняя состояние между вызовами. Для контроля за его жизненным циклом используется распределенная сборка мусора — лизинг. При этом объект получает некоторое время жизни, продлеваемое автоматически после каждого нового вызова. После исчерпания этого времени следует запрос к спонсору объекта (обычно к самому клиенту) о продлении жизни компонента. При отсутствии ответа объект уничтожается. Такой механизм позволяет экономить на коммуникации между клиентом и удаленным сервером.
3. Активируемый клиентом
Такой объект доступен только одному клиенту и сохраняет состояние между вызовами. Для контроля за жизненным циклом объекта используется лизинг.
Говоря об удаленных компонентах и сопоставляя .NET с СОМ нельзя не вспомнить об апартаментах. В одном процессе может быть несколько апартаментов, и ссылка на объект, полученная в одном апартаменте, не может непосредственно использоваться в другом апартаменте. Необходимо выполнить ее маршалинг между апартаментами. В.NET такой проблемы нет. Любая объектная ссылка (прокси на удаленный компонент) используется глобально по всему домену приложения.