加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

事件框架 POE 学习

发布时间:2020-12-16 00:37:20 所属栏目:大数据 来源:网络整理
导读:转载本站文章请注明,转载自: 扶凯 [http://www.php-oa.com] 本文链接: http://www.php-oa.com/2009/09/09/perl-poe-1.html POE结构: ???????????????? Kernel ????????????????????? | ???????????????? Session | _______________________________ | ? ?

转载本站文章请注明,转载自:扶凯[http://www.php-oa.com]

本文链接: http://www.php-oa.com/2009/09/09/perl-poe-1.html

POE结构:

???????????????? Kernel

????????????????????? |

???????????????? Session

| _______________________________ | ? ? ? ? ?

???????? | ? ? ? ? ? ? ?| ? ? ? ? ? ?|

Driver->Filter->Wheel->Components Kernel:

?POE管理会话的内核Kernel,它是POE核心,内部实现了IO读写信号回调等处理,简单应用程序与Kernel交互并不多。 Session:?? 会话抽象,会话中需要创建高层协议抽象,Session是一个处理线程,比如一个服务器程序每一个客户端连接就应该对应于一个Session,同理 Spider程序中对于每一个web服务器的连接也应该对应于一个Session,一个应用程序可以有很多Session。

Driver:???? 底层文件操作的抽象,在编程时不会直接用到,Wheel、Filter、Driver是对底层IO的封装。

Filter:???? 底层、中层协议操作的抽象,通常不会直接用到

Wheel:???? 高层协议操作的抽象,经常要用到

Components:POE提供的一些拿来就能用的组件

POE对象的数据结构:

  • $_[HEAP]:是会话唯一的数据存储区,相当有用的一个东西,它就是一个容器,相当于普通的Perl中的全局变量.这个在整个回话中,就用它 来通信;
  • $_[SESSION]:是指向会话自身的引用;
  • $_[KERNEL]:是指向会话管理内核的引用;
  • @_[ARG0..ARG9]:用于传递给各事件处理函数的参数,这是调用在传送参数给别的事件时,除开存在heap中的信息外的内容.都放在 这;
    my ($kernel, $session$heap) = @_[ KERNEL HEAP ];
    $currentItem$count[ ARG0..$#_ ;

如上,这是事件调用后,比较建议给通用的信息放到第一行.第二行是其它参数接收方法,这个中?@_[ ARG0..$#_ ],很象普通的子函数调用@_一样.

?

POE中几种事件调用的方法

  • yield:将一个事件放入当前会话fifo分派队列的末尾处,当队列中在其之前的事件被处理完毕之后,该事件将被触发以运行相应的事件句柄。
  • call : 是立即执行该事件.
  • post: 放到事件队列的最后,这个和call基本一样,但可以指定事件
  • delay: 从现在到设置的时间后,才运行事件. delay 可以加多个参数,它后面接的第二个参数为delay的时间,第三个参数为第一个调用事件的参数. delay后面只加事件名,不加参数的话,就是消掉这个事件,不在运行.
  • postback: 给事件放到后台,调用后才会还回
  • delay_set:? 和上面一样,几秒后运行,我还没有搞清它和 delay 的分别.

?

POE 的一些需要了解的东西

?

  • 句柄:它就是你给一个文件,设备,管套(socket)或管道的一个名字,以便帮助你记住你正处理的名字,并隐藏某些缓存等的复杂性。"
  • 事件; 事件就是真实世界中发生的一件事情。比如说:早晨打铃、面包从烤机里弹出、茶煮好了等。而在用户界面 上最常见的事件则是鼠标移动、按钮点击和键盘敲打等等。具体到程序软件事件,则往往是一些抽象的事件。也就是说,它不仅包括了发送给程序的外部活动,而且 也包括了一些在操作系统内部运行的事件。比如说,计时器到点了,socket建立了连接,下载完成等。
  • 事件句柄: 中心分配器的作用是将事件分配给不同的处理程序。这些处理程序就是事件句柄.它们的任务就是处理 相应事件,事件句柄就是Perl程序。它们因为使用了POE::Kernel传递的参数而不同于一般的perl程序。
  • POE::Session: 就是由POE::Kernel管理的“任务”。每一个session还拥有自己 的资源和事件句柄。
  • heap: 每一个session都有一个自己私有的存储空间,叫“heap”。它用于定义会话的heap, 传递给$_[HEAP],默认情况是匿名空Hash。这个就是上面指到的数据结构中的$_[HEAP]部分.记的,这个就象个全局引用,给需要的数据都放 到这个中.
  • POE::Kernel: 它提供了基于事件的操作系统核心服务。包括I/O事件、警报和其它计时事件、信号 事件和一些不被人意识到的事件。POE::Kernel提供不同的方法对这些事件进行设置,比如select_read(),delay()和sig()。POE::Kernel还能够跟踪事件发生源和与之相关的任务之间的关系。之所以能够这么做,是因为当事件发生时,它将跟踪 哪个任务被激活了。于是它便知道了哪个任务调用方法来使用了这些资源,而这些都是自动完成的。POE::Kernel也知道何事需将任务销毁。它检测任务 以确定是否还有事件需要处理,或者是哪个事需要释放占用的资源。当任务没有事件可以触发的时候,POE::Kernel就自动销毁该资源。
  • 参数: POE::Kernel是通过@_来传递参数的.也就是上面数据结构中提到的"@_[ KERNEL,SESSION,HEAP ] 和 @_[ARG0..ARG9]",前三个成员定义了发生该事件的session的上下文。 KERNEL 指向POE::Kernel运行实例的引用,指事件自身的名字. SESSION 指向发出事件的session的引用. HEAP 指向私有heap的引用 @_中剩下的成员属于事件自身,其中的具体内容依照被指派的事件类型而定。 举例说明:对于I/O事件,包括两个参数:一个是缓冲文件句柄,另一个是用来说明采取何种行为(input、output或者异常)的标记。POE还允许 改变参数的顺序和数量,而不会对程序造成影响。比如说,KERNEL,HEAP和ARG0分别是POE::Kernel实例、当前session的堆栈和 事件的第一个用户参数。它是传递给_start状态,即_start事件参数(ARG0..$#_)。 一次性以队列片段的形式赋值给程序参数。
    ;

?

实例分析

现在我们来拿Flw大大的程序来分析POE的工作原理. 注意,在这个程序基本上可以分为三部分

1) POE::Session->create,创建一个Session。

2) POE::Kernel->run, 启动框架消息分发。

3) sub start … 定义各种状态的回调函数。

 use POE;
?
   create POE::Session(
       inline_states =>
       {
           _start => &;session_start&;session_stop&;session_count}
   );
?
   print "启动 POE 内核...n";
   POEKernel->run;
   "POE 内核运行结束。exitsub session_start {
       "Session 启动。Session ID = "$_[SESSIONID";
       [HEAP{count} = 0[KERNELyield("count"}
?
   sub session_stop "Session 停止。Session ID = "".sub session_count {
       ( $heap ;
       $session_id ;
?
       $heap}++;
       printf "计数器 = %s;
?
       if < 5 ) {
           }

use POE; #加载了一些诸如POE::Kernel和POE:Sesson的模块并相应地做了一些初始化,并由POE::Session会根据不同的事件输出默认常 量给事件句柄的某些参数,如:KERNEL,HEAP,ARG0等等。

?

1.建立session 接着建立至少一个session。程序最少要有事情可以做.不然POE::Kernel会在最后一个session停止以后终止运行。

create POE(
   inline_states =>
   {
      _start 
      count  }
 ;

其中的inline_states(HASHREF)表示将事件名映射到处理该事件的代码引用。还有一个 object_states(LISTREF)将事件名映射到处理它们的对象方法,值是对象引用和对象方法引用组成的列表的引用。 两个事件(最上面提到的事件句柄)是由POE::Kernel自身所提供的。它们分别表示该session的启动(_start)和销毁(_stop)。 最后一个事件(count)是用户自定义事件,它被用于程序的逻辑之中。下面我们会来亲自写这几个函数.

?

2.启动POE::Kernel 由此便建立了一个用来探测并分派事件的主循环。我们使用print来打印POE::Kernel运行的开始处和结束点。

;
POE;
;

Kernel的run方法只有在所有session返回之后才会停止循环。

?

3.由上面定义的3个事件句柄:

_start句柄 在上面建立session的时候.首先从_start开始。_start的句柄将在sesson初始化完成之后开始运行,session在其自身的上下文 中使用它来实现输入引导。比如初始化heap中的值,或者分配一些必要的资源等等。 在该句柄中我们建立了一个累加器,并且发出了“count”事件以触发相应的事件句柄。

{
   ;
 }

在这,我们使用yield方法,将一个事件放入fifo分派队列的末尾处,当队列中在其之前的事件被处理完毕之后,该事件将被触发以运行相应的事件 句柄。

?

_stop句柄。 POE::Kernel将在所有session再无事件可触发之后,并且是在自身被销毁之前调用它。

}

count事件句柄。 该函数用来增加heap中的累加器计数,并打印累加结果。为了加深对yield的印象,我们现在使用yield方法来调用新的事件,这样也能够加深对 POE事件处理原理的理解。

{
  ;
  ;
?
  ++;
  ;
?
  }

POE输出:只要累加器计数未超过10,session将再yield一个count事件。因为不断地触发了 session_count句柄,使得当前session可以继续得以生存而不会被POE::Kernel清理。 当计数器到10时,便不再调用yield命令,session也将停止。一旦POE::Kernel检测到该session再没有事件句柄可被激发,便在 调用_stop事件句柄之后将其清理销毁。 以下是运行的结果:

Session 启动。Session ID 2
  启动 POE 内核...
  计数器 1
  计数器 2
  计数器 3
  计数器 4
  计数器 5
  Session 停止。Session ID 2.
  POE 内核运行结束。

有没有注意到,第一个count时本来是要打印0的,但是直接打印1.为什么,主要是因为下面,yield是需要事件完后才调用.

?

POE 其它注意

session->get_heap()? 通过 session 来得到 heap.

?

常用POE的组件

POE::API::Peek 这是一个可以查看 POE 核心事件的接口

POE::Wheel::Run 制造轮子,常用来做并发的事件

POE::Filter::Line? 行过滤器

POE::Wheel::SocketFactory 非阻塞套接字创建 ?????

POE::Component::Server::TCP 一个简单的TCP服务器

POE::Wheel::ListenAccept

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读