我是靠谱客的博主 爱撒娇溪流,这篇文章主要介绍libevent php教程,PHP之高性能I/O框架:Libevent(二),现在分享给大家,希望可以做个参考。

Event扩展

Event可以认为是替代libevent最好的扩展,因为libevent已经很久不更新了,而Event一直在更新,而且Event支持更多特性,使用起来也比libevent简单。

Event地址: http://pecl.php.net/package/event

Event文档: http://docs.php.net/event

和libevent一样,系统需要先安装 Libevent 库,因为都是基于 Libevent 库开发的:

yum install libevent-dev

然后安装PHP扩展。

PHP7安装:

pecl install event

Event扩展不支持PHP5。

注:后面的代码示例均使用的php7.1 + event环境。

基本使用

我们把libevent_tcp_server.php的例子改为Event实现的:

event_tcp_server.php

/**

* Created by PhpStorm.

* User: 公众号: 飞鸿影的博客(fhyblog)

* Date: 2018/6/23

*/

$receive = [];

$master = [];

$buffers = [];

$socket = stream_socket_server ("tcp://0.0.0.0:9201", $errno, $errstr);

if (false === $socket ) {

echo "$errstr($errno)n";

exit();

}

if (!$socket) die($errstr."--".$errno);

//stream_set_blocking($socket,0); //可选

$id = (int)$socket;

$master[$id] = $socket;

echo "waiting client...n";

//accept事件回调函数,参数分别是$fd, $events, $arg

function ev_accept($socket, $flag, $base){

global $receive;

global $master;

global $buffers;

$connection = stream_socket_accept($socket);

stream_set_blocking($connection, 0);//必须

$id = (int)$connection;

echo "new Client $idn";

$event = new Event($base, $connection, Event::READ | Event::PERSIST, 'ev_read', $id);

$event->add();

$master[$id] = $connection; //根据业务可选

$receive[$id] = ''; //根据业务可选

$buffers[$id] = $event; //根据业务可选

}

//read事件回调函数

function ev_read($buffer, $flag, $id)

{

global $receive;

global $master;

global $buffers;

//该方法里的$buffer和$master[$id]指向相同的内容

// var_dump(func_get_args(), $master[$id] );

//循环读取并解析客户端消息

while( 1 ) {

$read = @fread($buffer, 1024);

//客户端异常断开

if($read === '' || $read === false){

break;

}

$pos = strpos($read, "n");

if($pos === false)

{

$receive[$id] .= $read;

// echo "received:".$read.";not all package,continue recdiveingn";

}else{

$receive[$id] .= trim(substr ($read,0,$pos+1));

$read = substr($read,$pos+1);

switch ( $receive[$id] ){

case "quit":

echo "client close connn";

//关闭客户端连接

unset($master[$id]);//断开客户端连接

unset($buffers[$id]);//删除事件

break;

default:

// echo "all package:n";

echo $receive[$id]."n";

break;

}

$receive[$id]='';

}

}

}

//创建全局event base

$base = new EventBase();

//创建并设置 event:其中$events设置为READ | PERSIST ;回调事件为ev_accept,参数 $base

//PERSIST可以让注册的事件在执行完后不被删除,直到调用Event::del()删除.

$event = new Event($base, $socket, Event::READ | Event::PERSIST, 'ev_accept', $base);

$event->add();

echo "start run...n";

//进入事件循环

$base->loop();

//下面这句不会被执行

echo "This code will not be executed.n";

可以发现做的改动非常小,而且代码更简洁了。运行脚本后,我们使用telnet测试,效果一模一样。

使用Buffer

直接看例子吧,还是基于上面的例子改的,注释里写得很清楚了:

event_buffer_tcp_server.php

/**

* Created by PhpStorm.

* User: 公众号: 飞鸿影的博客(fhyblog)

* Date: 2018/6/23

*/

$receive = [];

$master = [];

$buffers = [];

$socket = stream_socket_server ("tcp://0.0.0.0:9201", $errno, $errstr);

if (false === $socket ) {

echo "$errstr($errno)n";

exit();

}

if (!$socket) die($errstr."--".$errno);

//stream_set_blocking($socket,0);//可选

$id = (int)$socket;

$master[$id] = $socket;

echo "waiting client...n";

//accept事件回调函数,参数分别是$fd, $events, $arg

function ev_accept($socket, $flag, $base){

global $receive;

global $master;

global $buffers;

$connection = stream_socket_accept($socket);

//stream_set_blocking($connection, 0);//可选

$id = (int)$connection;

echo "new Client $idn";

//新建EventBuffer 事件

$event = new EventBufferEvent($base, $connection, 0, 'ev_read', 'ev_write', 'ev_status', $id);

$event->setTimeouts(30, 30); //read and write timeout

$event->setWatermark ( Event::READ, 0, 0xffffff ); //Adjusts read and/or write watermarks

$event->setPriority(10);

$event->enable(Event::READ | Event::PERSIST);

$master[$id] = $connection; //如果去掉该行,客户端直接被断开

$receive[$id] = ''; //如果去掉该行,服务端无法正常收到消息

$buffers[$id] = $event; //如果去掉该行,客户端强制断开再连接,服务端无法正常收到消息

}

//read事件回调函数,参数分别是EventBufferEvent,arg

function ev_read($buffer, $id)

{

global $receive;

global $master;

global $buffers;

//该方法里的$buffer和$buffers[$id]指向相同的内容

// var_dump(func_get_args(), $buffers[$id], $master[$id]);

//循环读取并解析客户端消息

while( 1 ) {

$read = $buffer->read(65535);

// var_dump($read);

//客户端异常断开;这里可能返回NULL

if($read === '' || $read === false || $read === NULL){

break;

}

$pos = strpos($read, "n");

if($pos === false)

{

$receive[$id] .= $read;

echo "received:".$read.";not all package,continue recdiveingn";

}else{

$receive[$id] .= trim(substr ($read,0,$pos+1));

$read = substr($read,$pos+1);

switch ( $receive[$id] ){

case "quit":

echo "client close connn";

//关闭客户端连接

unset($master[$id]);//断开客户端连接

unset($buffers[$id]);//删除事件

break;

default:

// echo "all package:n";

echo $receive[$id]."n";

break;

}

$receive[$id]='';

}

}

}

function ev_write($buffer, $id)

{

echo "$id -- " ."n";

}

function ev_status($buffer, $events, $id)

{

echo "ev_status - ".$events."n";

}

//创建全局event base

$base = new EventBase();

//创建并设置 event:其中$events设置为READ | PERSIST ;回调事件为ev_accept,参数 $base

//PERSIST可以让注册的事件在执行完后不被删除,直到调用Event::del()删除.

$event = new Event($base, $socket, Event::READ | Event::PERSIST, 'ev_accept', $base);

$event->add();

echo "start run...n";

//进入事件循环

$base->loop();

//下面这句不会被执行

echo "This code will not be executed.n";

定时器(Timer)

直接看示例:

event_timer.php

/**

* Created by PhpStorm.

* User: 公众号: 飞鸿影的博客(fhyblog)

* Date: 2018/6/23

*/

$base = new EventBase ();

$n = 2 ; //sec

//初始化定时器

$e = Event :: timer ( $base , function( $arg ) use (& $e ) {

echo " $arg seconds elapsedn" ;

$e -> delTimer ();

}, $n );

//添加定时器

$e -> addTimer ( $n ); //sec

$base -> loop ();

运行:

$ php event_timer.php

2 seconds elapsed

和libevent扩展一样,Event::timer也是对Event的封装:

/**

* Created by PhpStorm.

* User: 公众号: 飞鸿影的博客(fhyblog)

* Date: 2018/6/23

*/

$base = new EventBase ();

$n = 2 ; //sec

//初始化定时器

$event = new Event($base, null, Event::TIMEOUT, 'ev_timer', $n );

$event->add($n);//sec

function ev_timer($fd, $what, $arg){

echo " $arg seconds elapsedn" ;

global $event;

$event->del();

}

$base->loop();

Event提供的定时器精度是秒。

信号(Signal)

Event 扩展提供了信号(Signal)操作的函数。

/**

* Created by PhpStorm.

* User: 公众号: 飞鸿影的博客(fhyblog)

* Date: 2018/6/23

*/

$base = new EventBase ();

//初始化信号事件

$e = Event :: signal ( $base , SIGUSR1, function( $signum , $arg ) use (& $e ) {

echo " Caught signal $signumn" ;

$e->delSignal(); //移除信号

}, '');

//安装信号

$e -> addSignal (); //sec

//发送信号

posix_kill(posix_getpid (), SIGUSR1);

$base -> loop ();

相比pcntl_signal,Event :: signal 高效很多。

总结

Libevent 非常强大,Event实现了其很多的接口供PHP调用,我这里仅是使用了常用的几个特性。由于Event能参考的资料实在是有限,这章写起来也相对难一些,例子里还是留了一些待再次理解。

最后

以上就是爱撒娇溪流最近收集整理的关于libevent php教程,PHP之高性能I/O框架:Libevent(二)的全部内容,更多相关libevent内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(117)

评论列表共有 0 条评论

立即
投稿
返回
顶部