page contents

swoole 第8次课 更上层楼:异步io模型与单进程Reactor

异步io模型, 单进程Reactor

1.理解事件

   11)生活事件  略

   12)框架事件

          attachments-2020-12-J9Gcq98U5fea6d04b4706.png

   13)linux事件

attachments-2020-12-4bnfDKoJ5fea6d2e9464b.png

2event事件扩展及安装

  21)两个文件的下载及上传,或直接远程下载到linux(或虚拟主机)

  libevent-2.18-stable.tar.gz

  event-2.3.0.taz

  把这两个文件下载下来,并上传至linux服务器(虚拟主机)

  或直接

  wget -c https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/libevent-2.1.8-stable.tar.gz -P /usr/local/src

 wget -c http://pecl.php.net/get/event-2.3.0.tgz -P /usr/local/src


 22)libevent-2.18-stable.tar.gz 安装,一定要先安装这个

 $ tar -zxvf libevent-2.1.8-stable.tar.gz

$ cd libevent-2.1.8-stable

$ ./configure --prefix=/usr/local/libevent-2.1.8

$ make

$ make install

23)event-2.3.0.taz安装
$ tar -zxvf event-2.3.0.tgz
$ cd event-2.3.0
$ phpize
$ ./configure --with-php-config=/www/server/php/74/bin/php-config   //注意,这里要对应版本
$ make
$ make install

24)配置及检验

vi  /www/server/php/74/etc/php.ini

增加:extension=event.so并保存退出

检验:php -m | grep event

attachments-2020-12-4Flnd8E05feb1863ef089.png


以上表明安装配置成功


25)扩展介绍

函数对象                               作用                                         参考地址

EventBase-object              用于监控所有的事件          https://php.golaravel.com/class.eventbase.html

Event-object                      事件类                          https://php.golaravel.com/class.eventbase.html


Event::__construct()      用于注册事件                 https://php.golaravel.com/event.construct.html

Event::add()                      添加事件                         https://php.golaravel.com/event.add.html

EventBase::__construct     创建一个应用监督事件 https://php.golaravel.com/eventbase.construct.html

EventBase::loop()             启动                                  https://php.golaravel.com/eventbase.loop.html


Event-flags               作用                                                                                                                                        参考地址

Event::READ            此标志表示当所提供的文件描述符(通常是流资源或套接字)准备好可读取时活动的事件。        https://php.golaravel.com/event.flags.html

Event::WRITE          标志表示当提供的文件描述符(通常是流资源或套接字)准备好写入时活动的事件。                   https://php.golaravel.com/event.flags.html

Event::SIGNAL        用于实现信号检测。参见下面的“构造信号事件”                                                                         https://php.golaravel.com/event.flags.html

Event::TIMEOUT     这个Event::TIMEOUT在构造事件时忽略标志:可以在事件发生时设置超时。加或者不是。     https://php.golaravel.com/event.flags.html

                                 设置为$什么当超时发生时,回调函数的参数

26)event的理解及运用

理解

attachments-2020-12-WrRZzvHE5feb1dbc58b5d.png

运用

attachments-2020-12-KPFVfxEB5feb1df307c15.png

深入Event::__construct()

Event::__construct

说明

public Event::__construct ( EventBase $base mixed $fd int $what callable $cb [, mixed $arg = NULL ] )

参数

base

The event base to associate with.

要关联的事件基础。即设置事件的应用类,能过EventBase $base,设置到Linux事件中

fd

stream resource, socket resource, or numeric file descriptor. For timer events pass -1 . For signal events pass the signal number, e.g. SIGHUP .

流资源、套接字资源或数字文件描述符。对于计时器事件通过-1 。对于信号事件,传递信号号,例如SIGHUP 

what

Event flags. See Event flags .事件标志

cb

The event callback. See Event callbacks .事件回调

arg

Custom data. If specified, it will be passed to the callback when event triggers.

自定义数据。如果指定,则在事件触发时,它将传递给回调。

返回值:Returns Event object. 返回事件对象


Event::add

Event::add — Makes event pending 使事件挂起

添加事件到设置事件应用类中

说明

public Event::add ([ float $timeout ] ) : bool

Marks event pending. Non-pending event will never occur, and the event callback will never be called. In conjuction with Event::del() an event could be re-scheduled by user at any time.

标记挂起的事件。非挂起事件永远不会发生,并且永远不会调用事件回调。与Event::del() 一起,用户可随时重新安排事件。

If Event::add() is called on an already pending event, libevent will leave it pending and re-schedule it with the given timeout(if specified). If in this case timeout is not specified, Event::add() has no effect.

如果Event::add() 在已挂起的事件上调用,libevent 将将其保持挂起状态,并在给定超时时重新计划它(如果指定)。如果未指定超时,则Event::add() 不起作用。

参数

timeout

Timeout in seconds. 可选参数, 如果事件构造时,标识参数为Event::TIMEOUT ,可设置时间。

返回值

Returns TRUE on success. Otherwise FALSE

261)小试牛刀

定时器 iostar\test\event\time.php

<?php
//设置事件的应用类
$eventBase = new EventBase();

//定义事件类 参数Event::PERSIST标志在事件上设置,则事件是永久性的。这意味着即使激活了调用,事件仍为挂起状态。
// 参数Event::del()方法,使其非挂起。
$event=new Event($eventBase,-1,Event::TIMEOUT | Event::PERSIST,function(){
//事件类的动作
echo microtime(true)."间隔2单位,我来了\n";
});

//添加事件到设置事件应用类中 参数可选,如果事件构造时,标识参数为Event::TIMEOUT ,可设置时间
$event->add(2);

//2 多个定时器
/*$event2=new Event($eventBase,-1,Event::TIMEOUT | Event::PERSIST,function(){
//事件类的动作
echo microtime(true)."间隔0.5单位,神来了\n";
});

//添加事件到设置事件应用类中 参数可选,如果事件构造时,标识参数为Event::TIMEOUT ,可设置时间
$event2->add(0.5);*/

//启动
$eventBase->loop();

运行如下:

attachments-2020-12-uubF3wWh5febc5b630c2e.png放开注释2,运行如下

attachments-2020-12-BSTnoQxQ5febc7430573d.png

262)小试牛刀

补充:事件构造的回调函数

Event callbacks

If a callback is registered for an event, it will be called when the event becomes active. To associate a callback with event one can pass a callable to either Event::__construct() , or Event::set() , or one of the factory methods like Event::timer() .

如果为事件注册了回调,则当事件变为活动状态时将调用该回调。若要将回调与事件关联,可以将可调用的项传递到事件:__construct() 或事件::set() 或工厂方法之一,如 Event::timer() 

An event callback should match the following prototype:

事件回调应与以下原型匹配:

callback ([ mixed $fd NULL [, int $what [, mixed $arg NULL ]]] ) : void

fd

The file descriptor, stream resource or socket associated with the event. For signal event fd is equal to the signal number.

与事件关联的文件描述符、流资源或套接字。对于信号事件等于信号数。fd

what

Bit mask of all events triggered.

触发的所有事件的位掩码。

arg

User custom data.

用户自定义数据

Event::timer() expects the callback to match the following prototype:

Event::timer() 要求回调与以下原型匹配

callback ([ mixed $arg NULL ] ) : void

arg

User custom data.

用户自定义数据。

Event::signal() expects the callback to match the following prototype:

Event::signal() 要求回调与以下原型匹配

callback ([ int $signum [, mixed $arg NULL ]] ) : void

signum

The number of the triggered signal(e.g. SIGTERM ).

触发信号的数量(例如SIGTERM )。

arg

User custom data.

用户自定义数据。

服务端iostarjhy\test\event\server.php

<?php
// 建立协议服务
$server = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);
var_dump($server);
$eventBase = new EventBase();

//Event 构造的回调参数
$event=new Event($eventBase,$server,Event::READ | Event::WRITE| Event::PERSIST,function($socket){
var_dump($socket);
$conn = stream_socket_accept($socket);
var_dump(fread($conn,65535));
fwrite($conn, 'hello client from sever of event,time ' . date('n/j/Y g:i a') . "\n");
fclose($conn);
});

$event->add();

$eventBase->loop();

客户端iostarjhy\test\event\client.php

<?php
// 连接服务端
$fp = stream_socket_client("tcp://192.168.204.168:8000");
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
fwrite($fp, "hello server-event");
while (!feof($fp)) {
echo fgets($fp, 1024);
}
fclose($fp);
}

运行

attachments-2021-01-HN9tPOLw5ff25b36a7880.png


与之前对比,原来时间长了会出现关于一直挂起的警告,而现在不会出现了。

263)了解 swoole的event运行

swoole的事件管理  event   https://wiki.swoole.com/#/event

swoole event 服务端 iostarjhy\test\event\swooleEvent.php

<?php
// 建立协议服务
$server = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);
var_dump($server);
//swoole_event_add(); //助手函数,同下,类静态方法
Swoole\Event::add($server, function($socket){
var_dump($socket);
$conn = stream_socket_accept($socket);
var_dump(fread($conn,65535));
fwrite($conn, 'hello client from swoole event,time ' . date('n/j/Y g:i a') . "\n");
fclose($conn);
});


swoole event 客户端 iostarjhy\test\event\ client2.php

<?php
// 连接服务端
$fp = stream_socket_client("tcp://192.168.204.168:8000");
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
fwrite($fp, "hello swoole event");
while (!feof($fp)) {
echo fgets($fp, 1024);
}
fclose($fp);
}


运行

attachments-2021-01-2uZN2EqG5ff2aef9c2e24.jpg

264) php-event运用的注意事项

swoole event的嵌套,正常,但php-event会有bug

swoole event 服务端iostarjhy\test\event\swooleEvent3.php

<?php
// 建立协议服务
$server = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);
var_dump($server);
//swoole_event_add(); //助手函数,同下,类静态方法
Swoole\Event::add($server, function($socket){
$conn = stream_socket_accept($socket);
//嵌套
Swoole\Event::add($conn, function($socket){
var_dump(fread($socket,65535));
fwrite($socket, 'hello client from swoole event3,time ' . date('n/j/Y g:i a') . "\n");
Swoole\Event::del($socket);
fclose($socket);
});
});

swoole event客户端 iostarjhy\test\event\client3.php

<?php
// 连接服务端
$fp = stream_socket_client("tcp://192.168.204.168:8000");
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
fwrite($fp, "hello swoole event3");
while (!feof($fp)) {
echo fgets($fp, 1024);
}
fclose($fp);
}

运行

attachments-2021-01-wYDkxxnn5ff2b61d854e8.png

php-event的嵌套 bug 

php-event嵌套服务端 iostarjhy\test\event\phpevent.php

<?php
// 建立协议服务
$server = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);
$eventBase = new EventBase();

$event=new Event($eventBase,$server,Event::READ | Event::WRITE| Event::PERSIST,function($socket) use (&$eventBase){
var_dump($socket);
$conn = stream_socket_accept($socket);
$event2=new Event($eventBase,$conn,Event::READ | Event::WRITE| Event::PERSIST,function($socket){
var_dump($socket);
var_dump(fread($socket,65535));
fwrite($socket, 'hello client from php event,time ' . date('n/j/Y g:i a') . "\n");
fclose($socket);
});
$event2->add();
});

$event->add();

$eventBase->loop();

php-event客户端 iostarjhy\test\event\phpEventClient.php

<?php
// 连接服务端
$fp = stream_socket_client("tcp://192.168.204.168:8000");
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
fwrite($fp, "hello php event");
while (!feof($fp)) {
echo fgets($fp, 1024);
}
fclose($fp);
}

运行

attachments-2021-01-Sct8bJkT5ff2ba7e17baf.png

虽未报错,但嵌套内的无效果,没有执行,即Event支持事件嵌套,但是不支持面向过程的方式嵌套,只支持面向对象的方式嵌套,具体参考如下:

类 iostarjhy\test\event\e.php
<?php

class e
{
protected $client;
protected $eventBase;

public function __construct($eventBase,$client,&$count)
{
$this->eventBase = $eventBase;
$this->client = $client;
}

public function hander()
{
$event=new Event($this->eventBase,$this->client,Event::READ | Event::WRITE| Event::PERSIST,function($socket){
//var_dump($socket);
//对于建立处理时间
var_dump(fread($socket,65535));
fwrite($socket, 'hello client from php event,time ' . date('n/j/Y g:i a') . "\n");
fclose($socket);
($this->count[(int) $socket][Event::READ | Event::WRITE| Event::PERSIST])->free();

});
$event->add();
$this->count[(int) $this->client][Event::READ | Event::WRITE| Event::PERSIST] = $event;
}
}
php -event 嵌套服务端:iostarjhy\test\event\phpevent2.php
<?php
require_once "e.php";
// 建立协议服务
$server = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);
var_dump($server);
$count=[];

$eventBase = new EventBase();

$event=new Event($eventBase,$server,Event::READ | Event::WRITE| Event::PERSIST,function($socket) use (&$eventBase,&$count){
var_dump($socket);
$conn = stream_socket_accept($socket);
(new e($eventBase,$conn,$count))->hander();
});

$count[(int) $server][Event::READ | Event::WRITE| Event::PERSIST] = $server;

$event->add();

$eventBase->loop();

php-event客户端 iostarjhy\test\event\phpEventClient.php 同上,略

运行

attachments-2021-01-HYX5QKND5ff2c6d3d2ee9.png

注意:最终推荐用swoole event

未完待续:swoole 第8次课 更上层楼:异步io模型与单进程Reactor 2

  • 发表于 2020-12-29 07:33
  • 阅读 ( 835 )

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
吉洪叶
吉洪叶

21 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1742 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章