КОММУНИКАЦИОННЫЙ ФЛЕШ ИЛИ FLASH COMMUNICATION SERVER MX
В мире интернет коммуникаций Macromedia не перестает радовать и приятно удивлять своими продуктами. После выхода линейки MX, слово 'FLASH' уже звучит все менее в значении - 'рекламный баннер', а приобретает значение интерактивного интернет приложения. Весьма показательна в этом отношении серверная платформа Flash Communication Server MX.
Macromedia Flash Communication Server MX используя механизмы передачи, синхронизации и хранения позволяет создавать разнообразные коммуникационные приложения в Macromedia Flash MX, которые позволяют обмениваться текстом, музыкой и видео(имеет свой видео формат FLV). Для примера можно использовать Flash Communication Server для чатов, онлайн видео и аудио конференций, и т.п.
Теперь приступим к практическому изучению сервера и созданию своего первого приложения.
Инсталляционный пакет качаем из http://www.macromedia.com/software/flashcom/. Следует заметить, что триал версия данного сервера, после окончания срока, поддерживает 5 одновременных подключений - это практически достаточно для разработки (следовательно бесплатно для нас программеров). После установки появляются два веб инструмента управления сервером: Communication App Inspector - инспектор запущенных приложений на сервере, Administration Console - глобальное управление сервером и его настройками. Нам больше понадобиться для работы Communication App Inspector, так как при его помощи можно тестировать серверные скрипты нашего приложения.
Серверные скрипты размещаются в отдельных папках в директории C:Program FilesMacromediaFlash Communication Server MXapplications. Создадим в этой директории свою папку и назовем ее 'mycomapp'. И что самое интересное таким образом мы практически уже создали серверное приложение, с которым можно соединяться (написание серверных скриптов будет описано в конце статьи).
Теперь нам надо создать клиентское приложение в Flash MX 2004. Создаем проект 'ComProject' к которому создаем и добавляем флеш документ 'ComClient'. Наша задача теперь соединиться с сервером для обмена информацией. Для соединения с сервером служит класс NetConnection имеющий набор методов и событий по работе с соединением. Адрес серверного приложения описываеться строкой Uniform Resource Identifier (URI).
Общий формат URI строки для соединения:
protocol:[//host][:port]/appname/[instanceName]
где protocol принимает значения rtmp - сокетное соединение или rtmpt - HTTP "туннелинг"; host - IP адресс где запущен сервер; port - по умолчанию RTMP соединение использует порт 1935, а RTMPT - 80; instanceName - по умолчанию равен '_definst_' (служит для разделения сессий в рамках одного серверного приложения, например для создания чат комнат и т.п.). Для более детальной информации читайте документацию к серверу.
Для примера следующие адреса являются синтаксически верными:
rtmp://www.myCompany.com/myMainDirectory/groupChatApp/HelpDesk rtmpt:/sharedWhiteboardApp/June2002 rtmp::1234/chatApp/room_name
Пишем код на первом фрейме флеш документа (желательно на отдельном слое):
// Открытие соединения с сервером // создаем экземпляр класса client_nc = new NetConnection(); // выполняем соединение с локальным серверным приложением mycomapp client_nc.connect("rtmp:/mycomapp");
// Сообщение о статусе соединения // определяем функцию обработчик события // изменения статуса соединения client_nc.onStatus = function(info) { // выводим информацию о статусе соединения trace("Level: " + info.level + " Code: " + info.code); }
Тестируем нашего клиента (Ctrl-Enter) и получаем в окне вывода(Output):
Level: status Code: NetConnection.Connect.Success
Из чего следует, что соединение было успешно выполнено!
Полезно запустить Communication App Inspector, в окне списке активных приложений мы должны увидеть запись "mycomapp/_definst_". Если мы принудительно выгрузим серверное приложение (закроем все соединения), выделив из списка наше и нажав кнопку "Unload", то в окне вывода Output получим сообщение:
Level: status Code: NetConnection.Connect.Closed
это было вызвано событием изменения статуса соединения с активного на закрытое. Использую такое событие можно строить программные индикаторы соединения приложения с сервером.
Реализуем обмен текстовой информацией между клиентами, для этого нам необходимо использовать класс SharedObject, который реализует работу механизма реал-тайм синхронизации данных между несколькими клиентскими флеш приложениями как расположенных локально или удаленно. Для доступа к данным класс имеет атрибут "data" после которого можно указывать имена переменных/объектов (например MySharedObject.data.myVar). Эти данные располагаются в оперативной памяти выделенной под серверное приложение и уничтожаются при выгрузке если предварительно не было выполнено их сохранение методом flush объекта SharedObject. Использование SharedObject локально аналогично "cookies", а удаленно как реал-тайм переносимый вывод данных.
Сначала помещаем на отдельный слой компонент TextArea и даем ему имя textArea_txt, затем дописываем к старому коду следующие строки:
// Открытие соединения с удаленным общим обьектом // создаем удаленый общий обьект, где client_nc.uri - URI обьекта // NetConnection использованое для соединения с сервером text_so = SharedObject.getRemote("sharedtext", client_nc.uri, true); // соединение с удаленными обьектом общих данных text_so.connect(client_nc);
// Событие изменения текста в текстовом поле textArea_txt.changeHandler =function(){ // обновление общего обьекта каждый раз, когда пользователь // набирает новый текст text_so.data.textValue = textArea_txt.text; };
// Событие изменения данных общего обьекта // каждый раз при изменении данных в общем обьекте, сервер // посылает синхронизирующее сообщение всем активным клиентам // это событие onSync вызываеться при обновлении данных в флеш ролике text_so.onSync = function(list) { // в параметре list передается список всех измененных обьектов // переменных созданных на аттрибуте data объекта SharedObject // с указанием статуса их изменения for (var i = 0; i < list.length; i++) if (list[i].name == "textValue" && list[i].code != "success"){ textArea_txt.text = text_so.data.textValue; break; } }
Запускаем одновременно два приложения, при наборе текста в одном из них - в другом текст будет изменяться автоматически. При открытии новых экземпляров наших приложений текстовое поле будет сразу содержать последний вариант текста, так как при соединении с объектом данных автоматически производиться их синхронизация.
Рис. 1 Синхронизация текстовой информации между приложениями
Если мы теперь принудительно выгрузим приложение при помощи Communication App Inspector, как делали выше, то при запуске приложения клиента текстовое поле будет пустым. Это вызвано тем, что данные хранились в оперативной памяти и были уничтожены при выгрузке серверного приложения.
Давайте попробуем создать хранилище данных, где данные будут сохраняться даже после остановки сервера. Для этого напишем серверный скрипт для нашего приложения, который будет выполнять сохранение данных.
Создаем файл с названием "main.asс" (только с этим названием скрипт будет выполнен при загрузке серверного приложения) и помещаем его в папку нашего серверного приложения "mycomapp".
Для работы с Flash Communication Server приложением служит класс Application, который обязательно используется в серверном скрипте. Он содержит информацию о запущенном экземпляре, количестве соединенных пользователей, обрабатывает события как на уровне сервера так и на уровне клиента. Когда клиент соединяется с сервером, сервер вызывает onAppStart , если экземпляр приложения еще не был запущен (соединение первого клиента). Следущий серверный onConnect метод происходит при автоматическом создании нового объекта Client для нового присоединяемого клиента. В этом методе можно подтвердить - accept или запретить reject соединение. На клиенте при этом происходит событие onStatus, извещающее о том подтверждено или отменено соединение. При закрытии клиентом соединения на сервере вызываеться метод onDisconnect. При выгрузке приложения выполняется onAppStop. Поведение и взаимодействие клиентского и серверного приложения показано на рисунке ниже.
Рис. 2 Процесс соединения
Используя данные знания напишем в файле "main.asс" скрипт.
// Событие загрузки серверного приложения // происходит при соединении первого клиента application.onAppStart = function(){ // создаем переменную серверного обьекта общих данных application.text_so = SharedObject.get("sharedtext", true); }
// Событие выгрузки серверного приложения application.onAppStop = function(){ // выполняем сохранение данных application.text_so.flush(); }
Следует отметить, что клиентские и серверные объекты SharedObject различаются, например серверный работает без метода connect, как видно из скрипта.
Выгрузим серверное приложения и запустим клиента, мы увидим последний введенный текст. Теперь информация общего объекта сохраняется на сервере. В папке нашего серверного приложения появилась папка "sharedobjects" которая содержит папки с сессиями, которые в свою очередь содержат файлы сохраненных общих обьектов. Так как мы соединялись по умолчанию, существует единственная папка "_definst_" и файл "sharedtext.fso" в нем. Название файла именно то, с каким именем мы связывали объект общих данных, в нем и сохраняется полностью наш объект.
Мы затронем еще одну важную вещь по работе с сервером - это вызов удаленной функции, как функции клиента из сервера, так и сервера из клиента.
Реализуем простую задачу оповещения клиента о том что он успешно был присоединен к серверу. Для этой цели мы должны добавить объекту сетевого соединения NetConnection функцию, которая будет нас оповещать, и при соединении вызвать ее для клиента с сервера. Для этого добавим к существующему коду приложения клиента следующие строки:
// Функция клиента добавленная на объект соединения // для возможности вызова ее с сервера client_nc.showMessage = function(msg){ // вывод сообщения с сервера trace(msg); }
А в серверном скрипте файла "main.asс", добавим обработку события соединения клиента:
// Событие присоединения нового клиента // newClient - обьект нового соединяющегося клиента application.onConnect = function(newClient){ // подтверждаем соединение клиента с сервером application.acceptConnection(newClient); // вызов с передачей параметров клиентской функции newClient.call("showMessage", false, "Hello from Server! Your IP:"+newClient.ip); }
Важно отметить что общий вид вызова метода call следующий
myNetConnection.call(methodName, [resultObj, p1, ..., pN])
параметры (в нашем случае он один) для вызываемой функции методом call перечисляются начиная с третьей позиции. На второй позиции находиться resultObj - объект для загрузки возвращаемого значения функции командой return. Наша функции ничего не возвращает, поэтому при вызове мы этот параметр ставим равным false. Как получать возвращаемые удаленной функцией значения описано ниже.
Выгрузим серверное приложение при помощи Communication App Inspector(это требуется делать каждый раз после редактирования, чтобы изменения в серверном скрипте вступили в силу) и запустим доработанное клиентское приложение. В Output получим сообщение:
Hello from Server! Your IP:127.0.0.1
Мы реализовали вызов клиентской функции с сервера, разберемся как вызвать серверную функцию из клиента.
Пусть нам надо вызвать серверную функцию, которая возвращала бы количество присоединенных клиентов к серверу в данный момент. Для этого можно воспользоваться механизмом прототипов для класса клиента, это позволяет нам просто и оптимально закрепить эту серверную функцию для всех клиентов, которые будут соединены с сервером. Допишем в серверном скрипте файла :
// обьявляем серверную функцию для всех клиентов Client.prototype.getTotalConnections = function(){ // возвращаем количество соединенных клиентов return application.clients.length; }
Осталось только вызвать эту функцию, для этого в приложении клиента допишем код, использующий сетевой подход к получению возвращаемого значения функции. Так как функция вызывается удаленно, то ее результат может пересылаться по сети определенное время, для этого приходиться создавать определенный объект ждущий загрузки результата:
// обьект для загрузки возвращаемого // значения серверной функции Result = function(){ // событие загрузки результата функции this.onResult = function(value){ trace("Total Connections: "+value); } } // вызов серверной функции с возвращением результата client_nc.call("getTotalConnections", new Result());
После перезагрузки серверного приложения (выгрузки приложения в Communication App Inspector и запуске клиента) в Output получим дополнительную строку:
Total Connections: 3
Этот начальный набор основный знаний по работе с Macromedia Flash Communication Server MX вполне достаточен для самостоятельного дальнейшего изучения. Этот сервер позволяет еще писать серверные компоненты, работать с аудио и видео потоками, что хорошо освещено в документации Macromedia. Основываясь на данном сервере можно создавать разнообразнейшие приложения начиная от сетевых игр, чатов и заканчивая конференциями и коммерческими сайтами.
Удачи и Побед! Джордж Форест
|