Warning EventListener::OPT_CLOSE_ON_FREE is forced when you transmit a "target" string.
The only way to not set EventListener::OPT_CLOSE_ON_FREE is to bind the socket before creating EventListener and use this socekt as "target".(PECL event >= 1.2.6-beta)
EventListener::__construct — Создаёт нового слушателя соединения, который связан с базой события
$base
,$cb
,$data
,$flags
,$backlog
,$target
Метод создаёт нового слушателя соединения, который связан с базой события.
base
База события.
cb
Значение с типом callable, которое вызывается при получении соединения.
data
Пользовательские данные, которые прикрепляются
к callback-функции параметра cb.
flags
Битовая маска из семейства констант
EventListener::OPT_*. Подробнее об этом рассказывает раздел
«Константы класса EventListener».
backlog
Управляет максимальным количеством ожидающих подключений,
которым сетевой стек должен разрешить в любое время ожидать в состоянии
«ещё не принято».
Дополнительную информацию смотрите в документации по функции listen
текущей системы.
При отрицательном значении параметра backlog
модуль Libevent сам попытается выбрать наилучшее значение
для параметра backlog.
При нуле модуль Event предполагает,
что функцию listen
уже вызвали на сокете target.
target
Строка, ресурс сокета или поток, связанный с сокетом.
При передаче в параметр target строкового аргумента,
строка разбирается как сетевой адрес. Строка интерпретируется
как путь сокета UNIX-домена, если содержит префикс
'unix:',
например 'unix:/tmp/my.sock'.
| Версия | Описание |
|---|---|
| PECL-модуль event 1.5.0 | Добавили поддержку сокетов UNIX-домена. |
Пример #1 Пример работы метода EventListener::__construct()
<?php
/*
* Простой сервер на основе слушателя соединений модуля libevent.
*
* Применение:
* 1) В одном окне терминала запустите команду:
*
* $ php listener.php 9881
*
* 2) В другом окне терминала откройте соединение, например:
*
* $ nc 127.0.0.1 9881
*
* 3) Начните печатать. Сервер должен повторить ввод.
*/
class MyListenerConnection
{
private $bev, $base;
public function __destruct()
{
$this->bev->free();
}
public function __construct($base, $fd)
{
$this->base = $base;
$this->bev = new EventBufferEvent($base, $fd, EventBufferEvent::OPT_CLOSE_ON_FREE);
$this->bev->setCallbacks(array($this, "echoReadCallback"), NULL,
array($this, "echoEventCallback"), NULL);
if (!$this->bev->enable(Event::READ)) {
echo "Не удалось включить READ\n";
return;
}
}
public function echoReadCallback($bev, $ctx)
{
// Скопируйте все данные из входного буфера в выходной буфер
// Вариант #1
$bev->output->addBuffer($bev->input);
/* Вариант #2 */
/*
$input = $bev->getInput();
$output = $bev->getOutput();
$output->addBuffer($input);
*/
}
public function echoEventCallback($bev, $events, $ctx)
{
if ($events & EventBufferEvent::ERROR) {
echo "Ошибка bufferevent\n";
}
if ($events & (EventBufferEvent::EOF | EventBufferEvent::ERROR)) {
//$bev->free();
$this->__destruct();
}
}
}
class MyListener
{
public $base,
$listener,
$socket;
private $conn = array();
public function __destruct()
{
foreach ($this->conn as &$c) $c = NULL;
}
public function __construct($port)
{
$this->base = new EventBase();
if (!$this->base) {
echo "Не удалось открыть событийную базу";
exit(1);
}
// Вариант #1
/*
$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!socket_bind($this->socket, '0.0.0.0', $port)) {
echo "Невозможно связать сокет\n";
exit(1);
}
$this->listener = new EventListener($this->base,
array($this, "acceptConnCallback"), $this->base,
EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE,
-1, $this->socket);
*/
// Вариант #2
$this->listener = new EventListener($this->base,
array($this, "acceptConnCallback"), $this->base,
EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE, -1,
"0.0.0.0:$port");
if (!$this->listener) {
echo "Не удалось создать слушателя";
exit(1);
}
$this->listener->setErrorCallback(array($this, "accept_error_cb"));
}
public function dispatch()
{
$this->base->dispatch();
}
// Эта callback-функция вызывается, когда есть данные для чтения на $bev
public function acceptConnCallback($listener, $fd, $address, $ctx)
{
// Получили новое соединение! Создайте для этого, что требуется. */
$base = $this->base;
$this->conn[] = new MyListenerConnection($base, $fd);
}
public function accept_error_cb($listener, $ctx)
{
$base = $this->base;
fprintf(STDERR, "Получил ошибку %d (%s) на слушателе."
."Выключение.\n",
EventUtil::getLastSocketErrno(),
EventUtil::getLastSocketError());
$base->exit(NULL);
}
}
$port = 9808;
if ($argc > 1) {
$port = (int) $argv[1];
}
if ($port <= 0 || $port > 65535) {
exit("Invalid port");
}
$l = new MyListener($port);
$l->dispatch();
?>Warning EventListener::OPT_CLOSE_ON_FREE is forced when you transmit a "target" string.
The only way to not set EventListener::OPT_CLOSE_ON_FREE is to bind the socket before creating EventListener and use this socekt as "target".