Лабораторная работа № 10-11
Создание серверной части многопользовательского чата
1. Цель работы
Целью работы является приобретение навыков в написании кода для серверной части приложения на языке программирования С#.
2. Состав рабочего места
2.1. Оборудование: IBM-совместимый персональный компьютер (ПК).
2.2. Программное обеспечение: операционная система Windows, интегрированная оболочка Visual Studio 2005 с установленным компонентом Visual C#.
3. краткие теоретические сведения
Виды серверных объектов
Существует два вида серверных объектов, отдаление которых поддерживается платформой. NET: известные (well-known) и активизированные клиентом (client-activated). Соединение с первыми устанавливается всякий раз, когда клиент посылает сообщение. С известным объектом постоянное соединение не устанавливается, в отличие от активизированных клиентом объектов.
Известные объекты, в свою очередь, делятся на два вида: одиночные (singleton) и одноразовые (single-call, то есть на один вызов). В случае одиночного известного объекта все сообщения от всех клиентов направляются одному объекту, работающему на сервере. Этот объект создается при запуске сервера и находится на нем для предоставления сервиса любому клиенту, который сможет к нему обратиться. Известные серверные объекты должны иметь конструкторы без параметров.
В случае с одноразовыми известными объектами каждое новое сообщение от клиента обрабатывается новым объектом. Это очень удобно на серверных фермах, где последовательные сообщения от одного клиента могут быть обработаны разными компьютерами, в зависимости от их загруженности.
Объекты, активизированные клиентом, обычно используются программистами, создающими для одного заказчика и программный продукт, и специализированный сервер, оказывающий ему услуги, В таком случае клиент и сервер устанавливают соединение, которое они поддерживают, пока сервер полностью не обслужит клиента.
Указание сервера с помощью интерфейса
Лучший способ разобраться в реализации доступа к объектам, реализованным в другом процессе, - разобрать конкретный пример. Создадим простой класс-калькулятор с четырьмя функциями.
Пример. Интерфейс Калькулятора
namespace Programming_CSharp
public interface ICalc
double Add(double x, double y);
double Sub( double x, double y);
double Mult(double x. double y);
double Div(double x. double y);
Сохраните этот файл под именем Icalc. cs и откомпилируйте его в файл ICalc. dll. Чтобы создать файл и откомпилировать его в среде , откройте новый проект типа Class Library, замените заготовку приложения, созданную средой разработки и выберите команду Build —> Build в меню Visual . В качестве альтернативы можно ввести исходный текст программы в Блокноте и откомпилировать исходный файл, введя в командную строку следующую команду:
csc /t library ICalc.cs
Реализация сервера через интерфейс обладает массой достоинств. Если реализовать калькулятор в виде класса, клиент будет вынужден указать при компоновке файл библиотеки динамической компоновки сервера, чтобы иметь возможность объявлять его экземпляры. Это существенно уменьшит преимущества, полученные в результате выделе-
ния объекта в сервер, поскольку изменения в классе на сервере повлекут за собой изменения на компьютере клиента. Иными словами, клиент и сервер будут тесно связаны друг с другом. Интерфейсы позволяют развести их. Впоследствии можно будет вносить изменения в реализацию сервера, но пока сервер выполняет договор, установленный интерфейсом, никакие изменения на компьютере клиента не потребуются.
Создание сервера
Чтобы создать сервер, используемый в рассматриваемом примере, создадим файл CalcServer. cs в новом проекте типа С# Console Application (не забудьте включить в проект ссылку на ICalc. dll) и откомпилируем его, выбрав команду Build —» Build в меню Visual . Если создавать код в Блокноте, файл CalcServer. cs следует откомпилировать, введя в командную строку команду:
csc /t:exe /r ICalc. dll CalcServer. cs
Класс Calculator реализует интерфейс ICalc. Он является производным от класса MarshalByRefObject, что позволит предоставить клиентскому приложению заместитель калькулятора:
public class Calculator ; MarshalByRefObject, ICalc
Реализация содержит конструктор, четыре метода, реализующие арифметические действия и еще кое-что.
В этом примере логика работы сервера помещена в метод M a i n ( ) в файле CalcServer. cs.
Сначала необходимо создать канал. В качестве транспортного протокола воспользуемся HTTP, потому что он проще, а постоянное соединение TCP/IP здесь не требуется. Платформа .NET предоставляет программисту тип HTTPChannel:
HTTPChannel chan = new HTTPChannel(65100)
Обратите внимание, что канал зарегистрирован на порту TCP/IP с номером 65100
Далее зарегистрируем канал с помощью класса CLR ChannelServices, для чего вызовем статический метод RegisterChannel:
ChannelServices RegisterChannel(chan);
В этом операторе платформе. NET сообщается о том, что сервер будет оказывать услуги по протоколу HTTP на порту 65100, подобно тому как IIS делает это на порту 80. Поскольку при регистрации HTTP-канала не был указан форматизатор, вызовы методов будут пользоваться форматизатором SOAP по умолчанию.
Теперь все готово к тому, чтобы класс RernotingConfiguratior зарегистрировал известный серверный объект. Для этого программист должен передать ему тип регистрируемого объекта и конечную точку(endpoint). Конечная точка - это имя, которое класс RemotingConfiguration свяжет с предоставленным типом. Оно будет завершать адрес. В то время как IP-адрес идентифицирует компьютер, а номер порта идентифицирует канал, конечная точка идентифицирует приложение, предоставляющее сервис. Чтобы получить тип объекта, вызовем статический метод GeiTypeO класса Туре и передадим методу полное имя объекта:
Type calcType = Type. GetType(“Programming_CSharp. Calculator”)
Кроме типа и конечной точки при регистрации объекта следует указать перечислимое значение, уточняющее, одиночный он или одноразовый (то есть Singleton или SingleCall):
RemotingConfiguration. RegisterWellKnownServiceType
(calcType, “theEndPoint”, WellKnownObjectMode. Singleton);
Вызов метода RegisterWellKnownServiceType() не пересылает данные, что называется, по проводам. Он просто создает заместитель объекта с помощью отражения.
Рассмотрим пошагово как создать удалённый сервер, используя Microsoft Visual C#
Первый шаг в создании серверного приложения - это создание объекта сервера. Объект сервера позволит приложению клиента связывается с компьютером сервера. Приложение клиента осуществляет это через прокси-объект, который создан на клиенте. В этом примере, объект сервера постоянно находится в Библиотеке Класса (DLL) и называется myRemoteClass.
1. Создайте новое приложение Class Library в Visual C#.NET. Назовите проект ServerClass. Class1 создан по умолчанию.
2. В Solution Explorer переименуйте файл Class1.cs в ServerClass.cs.
3. Откройте ServerClass.cs и переименуйте Class1 в myRemoteClass. Вы также должны переименовать заданный по умолчанию конструктор на класс так, чтобы это соответствовало имени класса. myRemoteClass, который должен наследовать MarshalByRefObject классу. Ваш класс должен выглядеть следующим образом:
public class myRemoteClass: MarshalByRefObject
{
public myRemoteClass()
{
//
// TO DO: Add constructor logic here.
//
}
}
4. Добавьте метод public к myRemoteClass, который отображает сообщение в консоли со значением строки, и возвращает true, если строка не пуста.
public bool SetString(String sTemp)
{
try
{
Console. WriteLine("This string '{0}' has a length of {1}", sTemp, sTemp. Length);
return sTemp!= "";
}
catch
{
return false;
}
}
5. Скомпилируйте проект, чтобы создать ServerClass. dll
6. Сохраните, и закройте проект.
Создание приложения удалённого сервера
После того, как Вы создали объект сервера, с которым будет связываться клиент, Вы должны зарегистрировать этот объект с помощью Remoting framework. Когда Вы регистрируете объект, Вы должны также запустить сервер и подключить его к порту, через который будут соединяться клиенты. Чтобы сделать это Вам нужен тип проекта, который выводит исполняемый файл.
Причина включения объекта сервера в отдельный проект состоит в том, чтобы Вы могли легко осуществить ссылку на объект сервера из проекта клиента. Если Вы включаете его в этот проект, Вы не можете ссылаться на него, потому что ссылки могут быть установлены только в DLL файлы.
1. создать новое консольное Приложение в Visual C#.NET, чтобы запустить удаленный сервер. Class1 создан по умолчанию.
2. В Solution Explorer , переименуйте Class1.cs файл к RemoteServer.cs.
3. Добавьте ссылку на пространство имён System.Runtime.Remoting
4. Добавьте ссылку на библиотеку ServerClass. dll, которую Вы создавали в предыдущем разделе.
5. Используйте директиву "using" для пространств имен "Remoting", "Remoting. Channels" и "Remoting. Channels. TCP" и для класса имен "ServerClass", чтобы Вам не потребовалось полные имена позднее в коде Вашей программы. Вы должны использовать директиву "using" перед всеми остальными объявлениями переменных.
using *****ntime. Remoting;
using *****ntime. Remoting. Channels;
using *****ntime. Remoting. Channels. Tcp;
6. Объявите переменную для инициализации объекта "TcpChannel", который будет использовать клиент для подключения к серверному приложению(порт 8085 в этом примере). Используйте метод "RegisterChannel" для регистрации канала с помощью служб канала. Добавьте следующий код объявления в процедуре Main Class1:
TcpChannel chan = new TcpChannel(8085);
ChannelServices. RegisterChannel(chan);
7. Вызовите метод RegisterWellKnownType объекта RemotingConfiguration,чтобы зарегестрировать объект ServerClass со структурой remoting, и определить следующие параметры:
• полное имя типа объекта, который зарегистрировался (т. е. ServerClass.myRemoteClass в этом примере), сопровождаемый блоком ServerClass. Определите оба пространства имён по имени класса. Поскольку Вы не определяли namespace в предыдущем разделе, заданный по умолчанию корень namespace используется.
• назовите конечную точку, где объект должен быть объявлен как RemoteTest. Клиенты должны знать его имя, чтобы соединиться с объектом.
• используйте режим SingleCall, чтобы определить заключительный параметр. Режим объекта определяет цикл жизни объекта, когда он активизирован на сервере. В случае использования SingleCall, новый класс создается для каждого запроса, который клиент делает, даже если тот же самый клиент вызывает тот же самый метод не раз. С другой стороны, объекты Singleton создаются только раз, и все клиенты связываются с тем же самым объектом.
RemotingConfiguration. RegisterWellKnownServiceType(
System. Type. GetType("ServerClass. myRemoteClass, ServerClass"),
"RemoteTest",
WellKnownObjectMode. SingleCall);
8. Используйте метод "ReadLine" объекта "Console" для сохранения серверного приложения запущенным.
System. Console. WriteLine("Hit <enter> to exit...");
System. Console. ReadLine();
9. Скомпилируйте проект.
10. Сохраните, и закройте проект.
4. Порядок выполнения работы
Порядок выполнения работы:
1. Составить программу удалённого сервера многопользовательского чата по одному из вариантов, приведенных в следующей таблице. Результаты вывести на экран дисплея.
№ варианта | Описание действия программы |
1 | Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться сверху, строка для ввода – максимум 30 символов: расположена под окном сообщений. Кнопка под строкой. |
2 | Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться снизу, строка для ввода должна состоять из 3-х и ограничиваться полем TextBox’a. Расположена под окном сообщений. Кнопка справа. |
3 | Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться сверху, строка для ввода – максимум 20 символов: расположена вверху чата. Кнопка справа. |
4 | Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться снизу, строка для ввода должна отображать только заглавные буквы. Расположение произвольное. |
5 | Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться сверху, строка для ввода – максимум 40 символов, находится сбоку окна чата. Кнопка под строкой. |
6 | Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться снизу, строка для ввода должна быть в TextBox’e 10х4. Кнопка – под строкой. |
7 | Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться сверху, строка для ввода – слева от окна чата: максимум 20 символов. Кнопка под строкой. |
8 | Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться снизу, строка для ввода слева, должна отображать только заглавные буквы. Кнопка над строкой. |
9 | Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться сверху, строка для ввода в виде TextBox’a 5х5 под окном чата со скролом. Кнопка справа. |
10 | Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться снизу, строка для ввода справа от окна чата: максимум 40 символов. Кнопка между окном чата и строкой. |
2. Ввести программу с клавиатуры с использованием Visual Studio 2005.
3. Отладить программу и запустить на выполнение.
5. Содержание отчета
В отчете должны быть представлен текст программы, значения вводимых величин и полученные значения выводимых величин.
6. Вопросы для самоконтроля
1. Какие существуют виды серверных объектов? В чём суть их использования?
2. В чём суть указания сервера с помощью интерфейса? Достоинства?
3. С помощью какого класса можно зарегистрировать канал?
4. Что такое форматизатор SOAP ?
5. Что такое конечная точка(endpoint) ?
6. Имеет значение использовать метод Singleton или SingleCall? В чём их различие?


