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".