此框架的扩展是LIBEVENT,php手册地址libevent,该框架了封装I/O事件,定时事件,中断信号事件,内核I/O复用函数支持EPOLL,POLL,SELECT,DEVPOLL,KQUEUE。框架官方网站libvent官网以下项目使用了该框架
本人注解的网络框架libevent源码内核原理分析 相关测试源码和分析流程以及笔记可联系本人获取
php libevent扩展安装地址
如果认真看过PHP手册的人安装php扩展是非常容易的. 本人安装的扩展是event2.2.1版本
<?php
class MyListenerConnection {
private $bev, $base;
public function __destruct() {
//将读写和异常回调清空同时释放BufferEvent相关内置的数据
$this->bev->free();
}
public function __construct($base, $fd) {
$this->base = $base;
//创建BufferEvent对象
//此对象内置了读写事件处理器,但并没有添加到I/O事件池中
//同时该对象分别创建input/outpu对象【内置创建】主要用于数据读写【接收和发送】
$this->bev = new EventBufferEvent($base, $fd, EventBufferEvent::OPT_CLOSE_ON_FREE);
//设置读写异常回调函数 【写回调并未设置】
$this->bev->setCallbacks(array($this, "echoReadCallback"), NULL,
array($this, "echoEventCallback"), NULL);
//将内置的写事件处理器添加到I/O事件池中,并且向内核事件表注册读就绪事件
if (!$this->bev->enable(Event::READ)) {
echo "Failed to enable READ\n";
return;
}
}
public function echoReadCallback($bev, $ctx) {
//读就绪事件发生后,内置的读事件处理器运行,然后运行此函数
//同时调用output,并把input【内置的读事件处理器读取的数据会放入到此input对象中】
//直接将接受的数据写入到客户端
$bev->output->addBuffer($bev->input);
}
public function echoEventCallback($bev, $events, $ctx) {
//异常回调
if ($events & EventBufferEvent::ERROR) {
echo "Error from 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) {
//创建event_base对象
//内置了I/O事件处理器池和信号事件处理器池
//同时也内置的定时时间堆
$this->base = new EventBase();
if (!$this->base) {
echo "Couldn't open event base";
exit(1);
}
//创建socket 并监听同时将此socket的读就绪事件注册到【经过I/O复用函数即事件多路分发器EventDemultiplexer管理】
//此socket 内置了监听事件处理器,客户端连接后,会调用此事件处理器,然后再运行用户设置的回调函数acceptConnCallBack函数
//EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE 标志位
//EventListener::OPT_CLOSE_ON_FREE 此参数会关闭低层连接socket
//EventListener::OPT_REUSEABLE 和前面说过的socket 选项有关【不清楚请翻阅之前我写过的东西】
//后面2个参数为ip和端口用于生成socket
$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 "Couldn't create listener";
exit(1);
}
//设置此socket事件处理器的错误回调
$this->listener->setErrorCallback(array($this, "accept_error_cb"));
}
public function dispatch() {
//内置了event_base_loop进行循环处理
//主要是调用如epoll的epoll_wait函数进行监听
//当任意I/O产生了就绪事件则会通知此进程
//此进程将会遍历就绪的I/O事件读取文件描述符
//并从I/O事件处理器池读取对应的事件处理器队链
//再将事件处理器插入到请求队列中
//两从请求队列中获取到事件并循环一一处理
//从而运行指定的回调函数
$this->base->dispatch();
}
/**
* @param $listener 上面的监听器
* @param $fd 产生就绪事件的文件描述符
* @param $address 客户端地址
* @param $ctx 用户自定义传递的参数
*/
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, "Got an error %d (%s) on the listener. "
."Shutting down.\n",
EventUtil::getLastSocketErrno(),
EventUtil::getLastSocketError());
$base->exit(NULL);
}
}
$port = 12345;
if ($argc > 1) {
$port = (int) $argv[1];
}
if ($port <= 0 || $port > 65535) {
exit("Invalid port");
}
$l = new MyListener($port);
//event_base_loop持续阻塞
//直到内核事件表中的I/O事件就绪产生才会运行相对的回调函数
$l->dispatch();
new EventBase() 对应c内部的event_base结构体
new EventListener 对应内部的evconnlistener结构体
new EventBufferEvent 对应内部的bufferevent结构体
更多相关的内容请阅读本人注解的内核libevent框架,不然你可能对这些知识点感到烧脑子