日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

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

發(fā)布時(shí)間:2025/7/14 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PHP之高性能I/O框架:Libevent(二) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Event擴(kuò)展

Event可以認(rèn)為是替代libevent最好的擴(kuò)展,因?yàn)閘ibevent已經(jīng)很久不更新了,而Event一直在更新,而且Event支持更多特性,使用起來(lái)也比libevent簡(jiǎn)單。

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

和libevent一樣,系統(tǒng)需要先安裝 Libevent 庫(kù),因?yàn)槎际腔?Libevent 庫(kù)開(kāi)發(fā)的:

yum install libevent-dev

然后安裝PHP擴(kuò)展。

PHP7安裝:

pecl install event

Event擴(kuò)展不支持PHP5。

注:后面的代碼示例均使用的php7.1 + event環(huán)境。

基本使用

我們把libevent_tcp_server.php的例子改為Event實(shí)現(xiàn)的:

event_tcp_server.php

<?php /*** Created by PhpStorm.* User: 公眾號(hào): 飛鴻影的博客(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事件回調(diào)函數(shù),參數(shù)分別是$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 $id\n";$event = new Event($base, $connection, Event::READ | Event::PERSIST, 'ev_read', $id); $event->add();$master[$id] = $connection; //根據(jù)業(yè)務(wù)可選$receive[$id] = ''; //根據(jù)業(yè)務(wù)可選$buffers[$id] = $event; //根據(jù)業(yè)務(wù)可選 }//read事件回調(diào)函數(shù) function ev_read($buffer, $flag, $id) {global $receive;global $master;global $buffers;//該方法里的$buffer和$master[$id]指向相同的內(nèi)容// var_dump(func_get_args(), $master[$id] );//循環(huán)讀取并解析客戶端消息while( 1 ) {$read = @fread($buffer, 1024);//客戶端異常斷開(kāi)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";//關(guān)閉客戶端連接unset($master[$id]);//斷開(kāi)客戶端連接unset($buffers[$id]);//刪除事件break;default:// echo "all package:\n";echo $receive[$id]."\n";break;}$receive[$id]='';}} }//創(chuàng)建全局event base $base = new EventBase(); //創(chuàng)建并設(shè)置 event:其中$events設(shè)置為READ | PERSIST ;回調(diào)事件為ev_accept,參數(shù) $base //PERSIST可以讓注冊(cè)的事件在執(zhí)行完后不被刪除,直到調(diào)用Event::del()刪除. $event = new Event($base, $socket, Event::READ | Event::PERSIST, 'ev_accept', $base); $event->add(); echo "start run...\n";//進(jìn)入事件循環(huán) $base->loop();//下面這句不會(huì)被執(zhí)行 echo "This code will not be executed.\n";

可以發(fā)現(xiàn)做的改動(dòng)非常小,而且代碼更簡(jiǎn)潔了。運(yùn)行腳本后,我們使用telnet測(cè)試,效果一模一樣。

使用Buffer

直接看例子吧,還是基于上面的例子改的,注釋里寫得很清楚了:

event_buffer_tcp_server.php

<?php /*** Created by PhpStorm.* User: 公眾號(hào): 飛鴻影的博客(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事件回調(diào)函數(shù),參數(shù)分別是$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 $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; //如果去掉該行,客戶端直接被斷開(kāi)$receive[$id] = ''; //如果去掉該行,服務(wù)端無(wú)法正常收到消息$buffers[$id] = $event; //如果去掉該行,客戶端強(qiáng)制斷開(kāi)再連接,服務(wù)端無(wú)法正常收到消息 }//read事件回調(diào)函數(shù),參數(shù)分別是EventBufferEvent,arg function ev_read($buffer, $id) {global $receive;global $master;global $buffers;//該方法里的$buffer和$buffers[$id]指向相同的內(nèi)容// var_dump(func_get_args(), $buffers[$id], $master[$id]);//循環(huán)讀取并解析客戶端消息while( 1 ) {$read = $buffer->read(65535);// var_dump($read);//客戶端異常斷開(kāi);這里可能返回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";//關(guān)閉客戶端連接unset($master[$id]);//斷開(kāi)客戶端連接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"; }//創(chuàng)建全局event base $base = new EventBase(); //創(chuàng)建并設(shè)置 event:其中$events設(shè)置為READ | PERSIST ;回調(diào)事件為ev_accept,參數(shù) $base //PERSIST可以讓注冊(cè)的事件在執(zhí)行完后不被刪除,直到調(diào)用Event::del()刪除. $event = new Event($base, $socket, Event::READ | Event::PERSIST, 'ev_accept', $base); $event->add(); echo "start run...\n";//進(jìn)入事件循環(huán) $base->loop();//下面這句不會(huì)被執(zhí)行 echo "This code will not be executed.\n";

定時(shí)器(Timer)

直接看示例:
event_timer.php

<?php /*** Created by PhpStorm.* User: 公眾號(hào): 飛鴻影的博客(fhyblog)* Date: 2018/6/23*/$base = new EventBase (); $n = 2 ; //sec//初始化定時(shí)器 $e = Event :: timer ( $base , function( $arg ) use (& $e ) {echo " $arg seconds elapsed\n" ;$e -> delTimer (); }, $n );//添加定時(shí)器 $e -> addTimer ( $n ); //sec$base -> loop ();

運(yùn)行:

$ php event_timer.php 2 seconds elapsed

和libevent擴(kuò)展一樣,Event::timer也是對(duì)Event的封裝:

<?php /*** Created by PhpStorm.* User: 公眾號(hào): 飛鴻影的博客(fhyblog)* Date: 2018/6/23*/$base = new EventBase (); $n = 2 ; //sec//初始化定時(shí)器 $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提供的定時(shí)器精度是秒。

信號(hào)(Signal)

Event 擴(kuò)展提供了信號(hào)(Signal)操作的函數(shù)。

<?php /*** Created by PhpStorm.* User: 公眾號(hào): 飛鴻影的博客(fhyblog)* Date: 2018/6/23*/$base = new EventBase ();//初始化信號(hào)事件 $e = Event :: signal ( $base , SIGUSR1, function( $signum , $arg ) use (& $e ) {echo " Caught signal $signum\n" ;$e->delSignal(); //移除信號(hào) }, '');//安裝信號(hào) $e -> addSignal (); //sec//發(fā)送信號(hào) posix_kill(posix_getpid (), SIGUSR1);$base -> loop ();

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

總結(jié)

Libevent 非常強(qiáng)大,Event實(shí)現(xiàn)了其很多的接口供PHP調(diào)用,我這里僅是使用了常用的幾個(gè)特性。由于Event能參考的資料實(shí)在是有限,這章寫起來(lái)也相對(duì)難一些,例子里還是留了一些待再次理解。

(未完待續(xù))


推薦

Redis 系列講座合集

內(nèi)容概要:Redis 最為目前炙手可熱的 Key-Value 數(shù)據(jù)庫(kù),常用做緩存、Session共享中間件,分布式鎖等等。
本系列課程包括:

講師是CSDN 博客專家,多年 Redis 使用經(jīng)驗(yàn)。感興趣的朋友可以點(diǎn)擊試看!


總結(jié)

以上是生活随笔為你收集整理的PHP之高性能I/O框架:Libevent(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。