- 论坛徽章:
- 0
|
Wheel:数据传送带
对于应用程序而言,输入输出是一个非常重要而且耗时的部分。通过使用Wheel,应用程序可以方便地监控IO事件并简化对输入输出操作的编写。对于Socket通讯程序来说,ListenAccept、SocketFactory、ReadWrite三种Wheel分别对应监听端口、建立连接和传送数据三种Socket操作。
1. ListenAccept
功用:处理一个监听端口的连接事件。
事件参数:AcceptEvent,其值在有客户连接时被触发。新建立的socket通过ARG0传送给处理函数。
2. SocketFactory
功用:建立到远程的连接。
事件参数:SuccessEvent,其值在连接完成时被触发。新建立的socket通过ARG0传送给处理函数。
3. ReadWrite
功用:读写数据。
事件参数:InputEvent,其值在当有数据到达时被触发。数据通过ARG0传送给处理函数。
FlushedEvent,其值在当所有缓冲的数据被发送出去后被触发。你可以在这个事件的处理函数中发送新数据、关闭连接等。
下面通过一个具体的聊天室server/client程序来说明Wheel的使用。客户端接收从服务端传送过来的数据,同时监控标准输入,如果有用户输入则把内容传送给服务端;服务端监听新的连接,并把每一个客户端传送过来的数据广播到所有的客户端。客户端这儿使用了一个Wheel ReadLine,它可以监控终端输入。
chats服务端
- use warnings;
- use strict;
- use IO::Socket;
- use POE qw /Wheel::ListenAccept Wheel::ReadWrite/;
- # 创建监听Socket及处理Session
- POE::Session->create
- ( inline_states =>
- { _start => \&start_server,
- new_connected => \&new_connected,
- client_input => \&client_input,
- }
- );
- POE::Kernel->run;
- sub start_server {
- my ($kernel, $heap) = @_[KERNEL, HEAP];
- my $server = IO::Socket::INET->new
- ( LocalPort => 8000,
- Listen => 16,
- Reuse => "yes",
- ) or die "can't make server socket: $@\n";
-
- $heap->{server} = POE::Wheel::ListenAccept->new
- ( Handle => $server,
- AcceptEvent => 'new_connected',
- );
- }
- sub new_connected {
- my ($heap, $client) = @_[HEAP, ARG0];
- my $wheel = POE::Wheel::ReadWrite->new
- ( Handle => $client,
- InputEvent => 'client_input',
- );
- # 系统中每个wheel的ID是唯一的
- $heap->{client}->{ $wheel->ID } = $wheel;
- }
- sub client_input {
- my ($heap, $input, $wid) = @_[HEAP, ARG0, ARG1];
- # 广播数据。如果愿意,可以屏蔽掉$wid,即发送消息的客户端
- map { $heap->{client}->{$_}->put( $input ) } keys %{$heap->{client}};
- }
复制代码
chatc客户端
- use warnings;
- use strict;
- use IO::Socket;
- use POE qw /Wheel::SocketFactory Wheel::ReadWrite Wheel::ReadLine/;
- POE::Session->create
- ( inline_states =>
- { _start => \&start_chat,
- connected => \&connected,
- connect_fail => \&connect_fail,
- server_input => \&server_input,
- user_input => \&user_input,
- }
- );
-
- POE::Kernel->run;
- sub start_chat {
- my $wheel = POE::Wheel::SocketFactory->new
- ( RemoteAddress => 'localhost',
- RemotePort => 8000,
- SuccessEvent => "connected",
- FailureEvent => "connect_fail",
- );
- $_[HEAP]->{server} = $wheel;
- }
- sub connected {
- my ($kernel, $heap, $socket) = @_[KERNEL, HEAP, ARG0];
- my $wheel = POE::Wheel::ReadWrite->new
- ( Handle => $socket,
- InputEvent => "server_input",
- ErrorEvent => "error_happened",
- );
- $heap->{server} = $wheel;
-
- my $console = POE::Wheel::ReadLine->new
- ( InputEvent => 'user_input'
- );
- # 告诉ReadLine监控终端
- $console->get( 'input your message, bye to quit: ');
- $heap->{console} = $console;
- }
- sub connect_fail {
- delete $_[HEAP]->{server};
- }
- sub server_input {
- my ($heap, $input) = @_[HEAP, ARG0];
- # 如果使用print "$input\n"会搞乱终端
- $heap->{console}->put( $input );
- }
- sub user_input {
- my ($heap, $input) = @_[HEAP, ARG0];
- if ($input =~ /(quit)|(exit)|(bye)/i) {
- delete $heap->{server};
- delete $heap->{console};
- return;
- }
- # 发送到服务端
- $heap->{server}->put( $input );
- # 继续监控终端
- $heap->{console}->get( 'input your message, bye to quit: ');
- }
复制代码 |
|