Лабораторная работа № 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-х и ограничиваться полем TextBoxa. Расположена под окном сообщений. Кнопка справа.

3

Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться сверху, строка для ввода – максимум 20 символов: расположена вверху чата. Кнопка справа.

4

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

5

Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться сверху, строка для ввода – максимум 40 символов, находится сбоку окна чата. Кнопка под строкой.

6

Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться снизу, строка для ввода должна быть в TextBoxe 10х4. Кнопка – под строкой.

7

Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться сверху, строка для ввода – слева от окна чата: максимум 20 символов. Кнопка под строкой.

8

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

9

Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться сверху, строка для ввода в виде TextBoxa 5х5 под окном чата со скролом. Кнопка справа.

10

Чат должен иметь окно для сообщений пользователей, строку для ввода сообщений, кнопку для отправки. Сообщения в окне должны появляться снизу, строка для ввода справа от окна чата: максимум 40 символов. Кнопка между окном чата и строкой.

2. Ввести программу с клавиатуры с использованием Visual Studio 2005.

3. Отладить программу и запустить на выполнение.

5. Содержание отчета

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

6. Вопросы для самоконтроля

1. Какие существуют виды серверных объектов? В чём суть их использования?

2. В чём суть указания сервера с помощью интерфейса? Достоинства?

3. С помощью какого класса можно зарегистрировать канал?

4. Что такое форматизатор SOAP ?

5. Что такое конечная точка(endpoint) ?

6. Имеет значение использовать метод Singleton или SingleCall? В чём их различие?