POE

2011-02-14  李卓华 

今天看了一下POE, 贴一段代码
server:
#! /usr/bin/perl
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];
print $input;
        # 广播数据。如果愿意,可以屏蔽掉$wid,即发送消息的客户端
        map { $heap->{client}->{$_}->put( $input ) } keys %{$heap->{client}};
}


client:
#! /usr/bin/perl
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: ');
}
386°/3868 人阅读/0 条评论 发表评论

登录 后发表评论