2024 年 PHP 日本会议

EventListener::__construct

(PECL event >= 1.2.6-beta)

EventListener::__construct创建一个与事件基础关联的新连接监听器

描述

public EventListener::__construct(
     EventBase $base,
     callable $cb,
     mixed $data,
     int $flags,
     int $backlog,
     mixed $target
)

创建一个与事件基础关联的新连接监听器。

参数

base

关联的事件基础。

cb

一个 callable,当接收到新连接时将被调用。

data

附加到 cb 的自定义用户数据。

flags

EventListener::OPT_* 常量的位掩码。参见 EventListener 常量

backlog

控制网络堆栈在任何时间允许等待未被接受状态的挂起连接的最大数量;有关更多详细信息,请参阅您系统 listen 函数的文档。如果 backlog 为负数,Libevent 会尝试为 backlog 选择一个合适的值;如果为零,Event 假设在套接字 (target) 上已经调用了 listen

target

可以是字符串、套接字资源或与套接字关联的流。如果 target 是字符串,则该字符串将被解析为网络地址。如果以 'unix:' 为前缀,例如 'unix:/tmp/my.sock',它将被解释为 UNIX 域套接字路径。

变更日志

版本 描述
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();
}

// 当$bev上有数据要读取时,调用此回调函数
public function acceptConnCallback($listener, $fd, $address, $ctx) {
// 我们得到了一个新的连接! 为其设置一个bufferevent。*/
$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(
"端口无效");
}

$l = new MyListener($port);
$l->dispatch();
?>
添加注释

用户贡献的注释 1 条注释

info-phpnet at ch2o dot info
10 年前
警告:当您传输“target”字符串时,会强制使用 EventListener::OPT_CLOSE_ON_FREE。

唯一不设置 EventListener::OPT_CLOSE_ON_FREE 的方法是在创建 EventListener 之前绑定套接字,并使用此套接字作为“target”。
To Top