Pull to refresh

Создание Comet-приложения с использованием Ajax Push Engine

Reading time6 min
Views5.9K

Введение


В этой статье я хочу поделиться опытом построения Web-приложения, работающего в реальном времени. Не буду углубляться в теорию, так как обзоры технологий уже были на хабре, и в сети их при желании найти не проблема. Предлагаю заняться непосредственно практикой.

Comet


Модель Comet позволяет создавать асинхронные Web-приложения, реагирующие на данные, которые приходят с сервера в реальном времени. В данном случае для ее реализации используется технология Long-polling на фреймворке Ajax Push Engine (APE). Суть технологии состоит в том, что браузер подключается к серверу и ждет до тех пор, пока не появятся данные. Как только они появляются, клиент их принимает и подключается снова. Если никаких данных не поступает, соединение разрывается после тайм-аута и снова устанавливается.

APE


APE представляет из себя программный комплекс с открытым исходным кодом, предназначенный для Ajax Push. Система включает в себя веб-сервер и Javascript Framework. APE позволяет передавать в браузер любые данные в реальном времени без каких-либо дополнительных приложений на стороне клиента. По заявлениям создателей свободно выдерживает нагрузку в 100000 соединений.


Установка и настройка


Установка и настройка сервера особых проблем не вызвали. Сразу хочу сказать, что в данном примере рассматривается установка на рабочем Web-сервере c CentOS 5 на борту. В зависимости от поставленных целей и платформы, реализация, разумеется будет отличаться. В случае если сервер используется для теста и работы на localhost'е, в официальной документации приведен пример быстрой настройки.



Начинается все, разумеется с установки. Тут тоже никаких проблем возникнуть не должно. На официальном сайте опубликованы различные типы пакетов, а так же исходники. Качаем и ставим.
Далее необходимо подготовить конфигурационный файл и указать APE-серверу с каким интерфейсом работать.
В разделе Server файла /etc/ape/ape.conf необходимо указать порт и интерфейс, который будет прослушиваться.

port = 6969
ip_listen = 69.65.59.1


Не забываем открыть порт для внешнего мира:

# iptables -I INPUT -p tcp --dport 9696 -j ACCEPT

И запускаем Comet-сервер:

# /usr/bin/aped --cfg /etc/ape/ape.conf

APE-демон запущен, но использовать по назначению его пока рано. Серверу для корректной работы необходимо выделить собственный поддомен и немного подкрутить настройки DNS.
Если вы используете cPanel или другую подобную панель это так же не составит труда.
В моем случае был создан поддомен:

ape.matvey.co

Затем CNAME-запись для редиректа запросов вида *.ape.matvey.co на ape.matvey.co.

*.ape.matvey.co IN CNAME ape.matvey.co

Теперь сервер готов общаться с клиентами.

Первое приложение


После этого необходимо взять с официального сайта JavaScript Framework и распаковать его куда вам будет удобней. В файле apeClientJS.js необходимо указать параметры для соединения с сервером. В моем случае это выглядело следующим образом:

APE.Config.baseUrl = 'http://matvey.co/apps/ape_test/jsf'; // путь к фреймворку
APE.Config.domain = 'matvey.co'; // основной домен
APE.Config.server = 'ape.matvey.co:6969'; // APE-сервер


Как иллюстрацию я приведу небольшое приложение, написанное на Python, которое будет с помощью APE рассылать клиентам простые текстовые сообщения. Связь между Python-скриптом и демоном осуществляется через http-протокол и Inlinepush. Более подробно об этом написано в официальной документации.
Итак, сначала ставим свой пароль в конфиг Inlinepush. Можно использовать и стандартный, но это по понятным причинам не рекомендуется. Обычно он находится в '/etc/ape/inlinepush.conf'.
Затем пишем небольшой скрипт на Python’e (или на чем вам удобней), который и будет передавать ape-серверу нужные данные через 6969 порт. Обращаться для этого необходимо к localhost'у.

import urllib2
import json

server = 'http://127.0.0.1:6969/0/?'

cmd = [{'cmd': 'inlinepush',
'params': {
'password': 'inlinepass5923',
'raw': 'DATA',
'channel': 'testchannel',
'data': {
'msg': 'Hey ya!'
}
}
}]

url = server + urllib2.quote(json.dumps(cmd))
response = urllib2.urlopen(url)
print response.read()


После запуска должен получиться примерно такой ответ:

# python test_ape.cgi
[{"time":"1301331051","raw":"ERR","data":{"code":"401","value":"UNKNOWN_CHANNEL"}}]


Слово ERR в данном случае означает только то, что канал пуст и никем не используется.
Теперь попробуем сделать что-то действительно работающее.
Для начала простую страницу, которая будет принимать сообщения от сервера.
Исходник страницы-клиента:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" dir="ltr" lang="en">
  <head> 
    <!-- Загрузка клиента APE. Указывается путь к вашему JSF. -->
    <script type="text/javaScript" src="/apps/ape_test/jsf/apeClientJS.js"></script>
  </head>
  <body>
    <script type="text/javaScript">
      var client = new APE.Client();
  // -- небольшая функция, которая будет генерировать случайные имена для каждого, кто входит на сайт   
      function randomString(length) {
        var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split('');          
        var str = '';
        for (var i = 0; i < length; i++) {str += chars[Math.floor(Math.random() * chars.length)];}
        return str;
      }
  // -- Для вывода полученных данных
      function createDiv(vartext) {
    var _body = document.getElementsByTagName('body') [0];
      var _div = document.createElement('div');
        var _text = document.createTextNode(vartext)
        _div.appendChild(_text);
        _body.appendChild(_div);
      }
      client.load();
      client.addEvent('load', function() {
  // -- Стартуем клиент, используя случайный name на 15 симвлолв. Чтобы наверняка :)
        client.core.start({"name":randomString(15)});
      });
      client.addEvent('ready', function() {
    createDiv("Connected");
        client.core.join('testchannel');
        client.addEvent('multiPipeCreate', function(pipe, options) {
        });
  // -- Собственно обработчик. Вывод данных на экран.
        client.onRaw('data', function(raw, pipe) {
        createDiv('Receiving : ' + unescape(raw.data.msg));
        });
      });
    </script>
  </body>
</html>


* This source code was highlighted with Source Code Highlighter.


Теперь мы имеем APE-сервер, приложение, передающее ему данные через inlinepush и клиента, который эти сообщения принимает.
Если открыть страницу-клиент и запустить скрипт на сервере получим следующий ответ:

[{"time":"1301340083","raw":"pushed","data":{"value":"ok"}}]

А клиент выведет заветное:

Receiving : Hey ya!

Результат запуска скрипта с разными параметрами представлен на скриншоте:



Теперь добавим в скрипт бесконечный цикл, таймаут на 10 секунд и запустим в фоновом режиме:

# python test_ape.cgi > /dev/null 2>& 1 &



Заключение


Целью статьи было продемонстрировать читателю на живом примере, что Comet-модель, являясь довольно мощным инструментом не представляет собой каких-то сложностей в реализации.

Результат работы можно посмотреть здесь.
Каждые 10 секунд на экране должно появляться сообщение от сервера.

На этом, пожалуй, пока все. В следующей статье я думаю написать о более серьезном и действительно работающем приложении.
Буду рад, если материал окажется кому-то полезным.

Полезные ссылки


Comet — обзорная статья
Официальный сайт APE
Tags:
Hubs:
+6
Comments6

Articles