600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > PHP之高性能I/O框架:Libevent(二)

PHP之高性能I/O框架:Libevent(二)

时间:2021-12-04 11:57:46

相关推荐

PHP之高性能I/O框架:Libevent(二)

Event扩展

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

Event地址: /package/event

Event文档: /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

<?php /*** Created by PhpStorm.* User: 公众号: 飞鸿影的博客(fhyblog)* Date: /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, $argfunction 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 $id\n";$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 recdiveing\n";}else{$receive[$id] .= trim(substr ($read,0,$pos+1));$read = substr($read,$pos+1);switch ( $receive[$id] ){case "quit":echo "client close conn\n";//关闭客户端连接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

<?php /*** Created by PhpStorm.* User: 公众号: 飞鸿影的博客(fhyblog)* Date: /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, $argfunction 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 $id\n";//新建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);//客户端异常断开;这里可能返回NULLif($read === '' || $read === false || $read === NULL){break;}$pos = strpos($read, "\n");if($pos === false){$receive[$id] .= $read;echo "received:".$read.";not all package,continue recdiveing\n";}else{$receive[$id] .= trim(substr ($read,0,$pos+1));$read = substr($read,$pos+1);switch ( $receive[$id] ){case "quit":echo "client close conn\n";//关闭客户端连接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

<?php/*** Created by PhpStorm.* User: 公众号: 飞鸿影的博客(fhyblog)* Date: /6/23*/$base = new EventBase ();$n = 2 ; //sec//初始化定时器$e = Event :: timer ( $base , function( $arg ) use (& $e ) {echo " $arg seconds elapsed\n" ;$e -> delTimer ();}, $n );//添加定时器$e -> addTimer ( $n ); //sec$base -> loop ();

运行:

$ php event_timer.php 2 seconds elapsed

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

<?php/*** Created by PhpStorm.* User: 公众号: 飞鸿影的博客(fhyblog)* Date: /6/23*/$base = new EventBase ();$n = 2 ; //sec//初始化定时器$event = new Event($base, null, Event::TIMEOUT, 'ev_timer', $n );$event->add($n);//secfunction ev_timer($fd, $what, $arg){echo " $arg seconds elapsed\n" ;global $event;$event->del();}$base->loop();

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

信号(Signal)

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

<?php/*** Created by PhpStorm.* User: 公众号: 飞鸿影的博客(fhyblog)* Date: /6/23*/$base = new EventBase ();//初始化信号事件$e = Event :: signal ( $base , SIGUSR1, function( $signum , $arg ) use (& $e ) {echo " Caught signal $signum\n" ;$e->delSignal(); //移除信号}, '');//安装信号$e -> addSignal (); //sec//发送信号posix_kill(posix_getpid (), SIGUSR1);$base -> loop ();

相比pcntl_signalEvent :: signal高效很多。

总结

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

(未完待续)

推荐

Redis 系列讲座合集

内容概要:Redis 最为目前炙手可热的 Key-Value 数据库,常用做缓存、Session共享中间件,分布式锁等等。

本系列课程包括:

讲师是CSDN 博客专家,多年 Redis 使用经验。感兴趣的朋友可以点击试看!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。