- PVSM.RU - https://www.pvsm.ru -
На хабре уже есть статья [1] по этой теме. Но фреймворк с тех пор сильно обновился и, к сожалению, по старой статье разобраться скорее всего будет проблематично. Кроме того, в изучении чего-то нового всегда самое сложное — это начало. Поэтому по свежей памяти постараюсь описать процесс старта хотя бы в общих чертах.
В принципе, установка достаточно полно описана [2] на официальном сайте [3].
Я предполагаю, что у вас уже установлен PHP с версией не младше 5.3. Поэтому описываю только остальное (на примере FreeBSD):
Это можно сделать по отдельности:
# cd /usr/ports/devel/php5-pcntl
# make install clean
# cd /usr/ports/devel/php5-shmop
# make install clean
# cd /usr/ports/net/php5-sockets
# make install clean
либо с помощью порта php5-extensions:
# cd /usr/ports/lang/php5-extensions
# make config
Отмечаем галочки напротив PCNTL, SHMOP и SOCKETS и устанавливаем:
# make install clean
При втором подходе в конце можно получить ошибку, что порт php5-extensions уже установлен. Тем не менее, сами библиотеки будут установлены нормально.
# cd /usr/ports/devel/pecl-libevent
# make install clean
# cd /usr/ports/devel/git
# make install clean
# 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
В принципе, сама установка на этом завершена. Теперь стоит попробовать запустить первое приложение. Для этого возьмем пример из комплекта — ExampleWebSocket. Для этого необходимо сделать несколько шагов:
/usr/local/phpdaemon/applications. Здесь будут храниться наши приложения./usr/local/phpdaemon/conf/phpd.conf:
user www;
group www;
max-workers 8;
min-workers 1;
start-workers 1;
max-idle 0;
WebSocketServer {
enable 1;
listen "tcp://0.0.0.0";
listen-port 8047;
privileged;
}
ExampleWebSocket {}
Теперь пробуем запустить наш сервер:
# phpd start
Все должно пройти нормально и в логах (/var/log/phpdaemon.log) мы должны увидеть примерно следущее:
Pool:WebSocketServer up.
W#73942 ExampleWebSocket up.
Spawning 7 worker(s).
W#73948 ExampleWebSocket up.
W#73943 ExampleWebSocket up.
W#73944 ExampleWebSocket up.
W#73945 ExampleWebSocket up.
W#73946 ExampleWebSocket up.
W#73947 ExampleWebSocket up.
W#73949 ExampleWebSocket up.
Хотелось бы предложить в дополнение к идущему в комплекте еще один пример WebSocket-приложения. Думаю, лишний пример никогда не будет вреден разбирающемуся в новом человеку.
Сразу следует оговориться, что в данный момент времени официальная документация сильно устарела. Разработчик обещает исправить это в будущем. Тем не менее, всегда можно открыть интересующий класс фреймворка, найти нужный метод и разобраться как он работает. Чаще всего это не отнимает много времени: код интуитивно понятен.
Итак:
<?php
class MyWebSocket extends AppInstance {
public $enableRPC=true; // Без этой строчки не будут работать широковещательные вызовы
public $sessions=array(); // Здесь будем хранить указатели на сессии подключившихся клиентов
// С этого метода начинается работа нашего приложения
public function onReady() {
$appInstance = $this;
// Метод timerTask() будет вызываться каждые 5 секунд
$this->timerTask($appInstance);
// Наше приложение будет доступно по адресу ws://site.com:8047/myws
WebSocketServer::getInstance()->addRoute('myws', function ($client) use ($appInstance) {
$session=new MyWebSocketRoute($client, $appInstance); // Создаем сессию
$session->id=uniqid(); // Назначаем ей уникальный ID
$this->sessions[$session->id]=$session; //Сохраняем в массив
return $session;
});
}
function timerTask($appInstance) {
// Отправляем каждому клиенту свое сообщение
foreach($this->sessions as $id=>$session) {
$session->client->sendFrame('This is private message to client with ID '.$id, 'STRING');
}
// После отправляем всем клиентам сообщение от каждого воркера (широковещательный вызов)
$appInstance->broadcastCall('sendBcMessage', array(Daemon::$process->pid));
// Перезапускаем наш метод спустя 5 секунд
Timer::add(function($event) use ($appInstance) {
$this->timerTask($appInstance);
$event->finish();
}, 5e6); // Время задается в микросекундах
}
// Функция для широковещательного вызова (при вызове срабатывает во всех воркерах)
public function sendBcMessage($pid) {
foreach($this->sessions as $id=>$session) {
$session->client->sendFrame('This is broadcast message from worker #'.$pid, 'STRING');
}
}
}
class MyWebSocketRoute extends WebSocketRoute {
public $client;
public $appInstance;
public $id; // Здесь храним ID сессии
public function __construct($client,$appInstance) {
$this->client=$client;
$this->appInstance=$appInstance;
}
// Этот метод срабатывает сообщении от клиента
public function onFrame($data, $type) {
// Отправляем ему ответ
$this->client->sendFrame('Server receive from client #'.$this->id.' message "'.$data.'"', 'STRING');
}
// Этот метод срабатывает при закрытии соединения клиентом
public function onFinish() {
// Удаляем сессию из массива
unset($this->appInstance->sessions[$this->id]);
}
}
user www;
group www;
max-workers 8;
min-workers 1;
start-workers 1;
max-idle 0;
Pool:WebSocketServer {
enable 1;
listen "tcp://0.0.0.0";
listen-port 8047;
privileged;
}
MyWebSocket {}
<script type="text/javascript">
function add(text) {
document.forms[0].b.value=text+"n"+document.forms[0].b.value;
}
if("WebSocket" in window) {
var timer;
var ws=new WebSocket("ws://site.com:8047/myws");
ws.onopen=function() {
add('Connection opened');
timer=window.setInterval(function() {
var date = new Date();
var message='ping at '+date.getSeconds();
ws.send(message);
add('Client sent message "'+message+'"');
}, 30000);
};
ws.onmessage=function(evt) {
add('Message from server: "'+evt.data+'"');
};
ws.onclose=function() {
add('Connection closed');
window.clearTimeout(timer);
};
} else {
alert("Your browser doesn't support WebSocket");
}
</script>
<form>
<textarea name="b" style="width:100%;height:100%"/></textarea>
</form>
# phpd restart
После этого JS-клиент начинает взаимодействовать с сервером и в браузере будут выводиться все их взаимодействия.
У сервера имеется таймаут равный двум минутам (120 секунд). Соответственно, клиент должен периодически посылать серверу сообщения «пустышки», чтобы сервер не счел его неактивным и не отключил. И не забудьте заменить site.com на адрес вашего хоста.
Автор: bartwell
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/websocket/26233
Ссылки в тексте:
[1] статья: http://habrahabr.ru/post/82140/
[2] описана: https://github.com/kakserpom/phpdaemon/wiki/Установка-(Общее)
[3] официальном сайте: http://phpdaemon.net/
[4] Источник: http://habrahabr.ru/post/168059/
Нажмите здесь для печати.