Серверы FastCGI, HTTP, CGI, FlashPolicy, Telnet, клиенты mysql, memcached, mongodb — вот неполный список функционала, реализованного в этом демоне, созданном российским программистом Василием Зориным.
Впрочем, нас сейчас интересуют только WebSocket, и это phpDae-mon тоже умеет. Процесс установки фрэйворка имеет свои нюансы, поэтому остановимся на нем чуть подробней.
PhpDaemon требует для своей работы библиотеку libevent — это кроссплатформенная библиотека для асинхронной работы с сетью, предоставляющая механизм, использующий функции обратного вызова. В репозитории Pecl имеется расширение для работы с libevent посредством php, но, чтобы его собрать, нам, возможно, понадобится утилита phpize из пакета php-devel. Впрочем, это обстоятельство нас не должно останавливать.
Действуем:
$ sudo aptitude install php5-dev
Это естественно для пользователей Debian или Ubuntu. Если у вас Red Hat, Fedora или CentOS, команда будет:
$ sudo yum install php53-devel
Если вы используете Windows… ну, в общем, лучше поставить виртуальную машину.
Далее устанавливаем расширение libevent (сама библиотека должна быть уже установлена):
Pecl install libevent
После установки необходимо в php. ini прописать следующую строчку, если ее нет в наличии:
Extension=libevent. so
(Нам важно это сделать для cli-интерпретатора, то есть путь к конфигурационному файлу будет вида: /etc/php5/cli/php. ini.)
И наконец, устанавливаем PhpDaemon:
Cd /usr/local
Git clone git://github. com/kakserpom/phpdaemon. git chmod +x phpdaemon/bin/phpd
Ln — s /usr/local/phpdaemon/bin/phpd /usr/bin/phpd
Для DEBIAN-like:
Ln — s /usr/bin/phpd /etc/init. d/phpd update-rc. d phpd defaults
Запускаем:
phpd start
Хотя с запуском мы наверняка поторопились, и, возможно, в консоль вывалятся несколько ошибок. Это не беда, сейчас все исправим. Прежде всего редактируем файл конфигурации — phpdaemon/conf/ phpd. conf. Он должен будет выглядеть примерно так:
## Config file
User root; group root;
Max-workers20; min-workers20;
Max-requests 1m;
Max-idle 0;
Example { enable 1: privileged;
}
ServerStatus { enable 1; privileged;
}
Log-errors 1;
HTTP {
Privileged; enable 1; listen-port 8080:
}
Server { privileged;
}
ExampleWebSocket { enable 1;
Path /usr/local/lib/phpdaemon/applications/ExampleWebSocket. php:
Listenport 8047; user www;
Group www;
}
WebSocketOverCOMET { enable 1;
}
# other applications…
Path = /usr/local/lib/phpdaemon/AppResolver. php
Include conf. d/*.conf:
Я тут не буду останавливаться на деталях настройки среды phpdaemon, весь конфигурационный файл я привожу только для того, чтобы его можно было без изменений использовать в своих опытах читателю. Наиболее важны конструкции Server и Example-WebSocket. Первая из них выключает веб-сокеты, вторая регистрирует тестовое приложение. Параметр path указывает на его физическое размещение.
Очень важным параметром конфигурации является строчка
Path = /usr/local/lib/phpdaemon/AppResolver. php,
Показывающая наш путь до резолв-файла (файла, разбирающего запросы и связывающего их с приложением). Сам этот файл у нас будет максимально прост:
Практически на этом настройка phpdaemon завершена. По адресу, указанному нами в phpd. conf (hpdaemon/applications/), разместим файл ExampleWebSocket. php из каталога примеров phpdaemon (hpdaemon/applications/app-examples). Особо останавливаться на его содержании пока не имеет смысла, скажем только, что вся функциональность этого сервиса заключается в отправке слова «pong» в ответ на поступивший внешний запрос «ping».
Теперь мы озаботимся клиентской частью. В дистрибутив phpdae-mon входит хороший инструментарий для тестирования технологий. В папке phpdaemon/clientside-connectors/websocket/ находятся набор js-файлов и пример html-страницы, работающей с веб-сокетами, требующей минимальной настройки (рис. 105). Причем для браузеров, не поддерживающих WebSocket, выполнена эмуляция процесса с использованием технологий COMET/Long Pooling и даже flash. Но нам это не очень интересно, не будем искать легких путей и напишем свой WebSocket-клиент:
}
Function messageEvent(msg){ alert(msg. data):
}
Function closeEvent(){ alert("close");
}
</script>
<button onclick="create();">Create WebSocket</button> <button onclick="sendEvent(‘ping’);">Send ping</button> <button onclick="WS. close();">Close WebSocket</button>
</body>
</html>
Рис. 105. Работаем с WebSockets
Тут мы видим три кнопки, первая из которых создает сокет (и, соответственно, устанавливает соединение), вызывая функцию WebSocketConnection, которая, в свою очередь, создает объект WebSocket(), параметром конструктора которого является url нашего WebSocket-приложения. Второй, необязательный параметр — протокол, их может быть несколько.
После установки соединения (нас известит об этом соответствующий alert) можно пользоваться клавишей Send ping, посылающей сообщение в сокет. При получении сообщения со стороны сервера срабатывает событие onmessage, в результате которого в нашем случае будет выведено сообщение с ответом сервера (рис. 106). Клавиша Close WebSocket закрывает сокет — поле этого взаимодействие
С сервером прекращается. Данные посылаются и принимаются в виде строк, но ничто не мешает обмениваться и JSON-объектами:
Function sendText() { var msg ={
Type: "message", text: "Hello WebSockets.!", id: clientID, date: Date. now()
};
WS. send(JSON. stringify(msg));
Pong |
||
— Prevent this page from creating additional dia |
Ogs. |
|
OK |
I |
Рис. 106. Ответ через WebSocket
Словом, все, как в обычном клиент-серверном веб-взаимодействии. Как выглядит серверная часть, нас, строго говоря, не должно интересовать, но давайте взглянем на ее реализацию просто для общего развития.
В файле phpdaemon/application/ExsampleWebSocket. php описаны два класса (автор кода — Zorin Vasily <kak. serpom. po. yaitsam@gmail. com>):
* Called when new frame received.
* @param string Frame’s contents.
* @param integer Frame’s type.
* @return void */
Public function onFrame($data, $type) { if ($data === ‘ping’) {
$this->client->sendFrame(‘ pong’, WebSocketSERVER::STRING, function($client) {
Daemon::log(‘ExampleWebSocket: ‘pong’ received by client.’); }
):
}
}
}
Первый из них вызывается при создании веб-сокета и возвращает объект нового сеанса работы с ним. Второй является реализацией этого сеанса и содержит метод onFrame, принимающий сообщение и отсылающий ответ.
Что мы можем теперь получить, исходя из имеющегося арсенала средств? Да практически все, препятствий в виде HTTP-протокола больше нет. Вернее, сам HTTP никуда не делся, но особенности его архитектуры — больше не помеха. Помеха в другом — слабой пока поддержке технологии как в браузерах, так и на веб-серверах. Но, я думаю, никто не сомневается, что это все временно. Гораздо более существенным выглядит другой, «врожденный» недостаток технологии — отсутствие ограничения срока жизни запроса. Дело в том, что WebSockets — это TCP-сокет, а не HTTP-запрос, он не имеет природы «запрос/ответ на запрос», и это, помимо преимуществ, имеет и обратную сторону — неудобство работы сервисов, ограниченных одним запросом. Ну что же, серебряной пули не существует, просто разработчику надо всегда иметь в виду такое поведение при взаимодействии с сервером.
Добавить комментарий