Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Вопрос к знатокам POE


Автор: shamber 12.11.2006, 23:19
Люди помогите с ним.
Не догоняю...

вообщем нужно организовать такую фишку.

Использую рецепт из cookbooka. Using SocketFactory and ReadWrite

Код

#!/usr/bin/perl

# http://poe.perl.org/?POE_Cookbook/TCP_Servers

use strict;
use warnings;

use Socket;
use POE qw(Wheel::SocketFactory
  Wheel::ReadWrite
  Driver::SysRW
  Filter::Stream
);

#####
# MAIN
#####

local $| = 1;
our $debug      = 1;        # be very very noisy
our $serverport = 11211;    # 'poe' in base10 :P

fork and exit unless $debug;

POE::Session->create(
    inline_states => {
        _start => \&parent_start,
        _stop  => \&parent_stop,

        socket_birth => \&socket_birth,
        socket_death => \&socket_death,
      }
);

# $poe_kernel is exported from POE
$poe_kernel->run();

exit;

####################################

sub parent_start {
    my $heap = $_[HEAP];

    print "= L = Listener birth\n" if $debug;

    $heap->{listener} = POE::Wheel::SocketFactory->new(
        BindAddress  => '127.0.0.1',
        BindPort     => $serverport,
        Reuse        => 'yes',
        SuccessEvent => 'socket_birth',
        FailureEvent => 'socket_death',
    );
}

sub parent_stop {
    my $heap = $_[HEAP];
    delete $heap->{listener};
    delete $heap->{session};
    print "= L = Listener death\n" if $debug;
}

##########
# SOCKET #
##########

sub socket_birth {
    my ( $socket, $address, $port ) = @_[ ARG0, ARG1, ARG2 ];
    $address = inet_ntoa($address);

    print "= S = Socket birth\n" if $debug;

    POE::Session->create(
        inline_states => {
            _start => \&socket_success,
            _stop  => \&socket_death,

            socket_input => \&socket_input,
            socket_death => \&socket_death,
        },
        args => [ $socket, $address, $port ],
    );

}

sub socket_death {
    my $heap = $_[HEAP];
    if ( $heap->{socket_wheel} ) {
        print "= S = Socket death\n" if $debug;
        delete $heap->{socket_wheel};
    }
}

sub socket_success {
    my ( $heap, $kernel, $connected_socket, $address, $port ) =
      @_[ HEAP, KERNEL, ARG0, ARG1, ARG2 ];

    print "= I = CONNECTION from $address : $port \n" if $debug;

    $heap->{socket_wheel} = POE::Wheel::ReadWrite->new(
        Handle => $connected_socket,
        Driver => POE::Driver::SysRW->new(),
        Filter => POE::Filter::Stream->new(),

        InputEvent => 'socket_input',
        ErrorEvent => 'socket_death',
    );

    $heap->{socket_wheel}->put(
        "1 Welcome. Say something. I'll say it back.\n\n" );
}

sub socket_input {
    my ( $heap, $buf ) = @_[ HEAP, ARG0 ];
    $buf =~ s/[\r\n]//gs;
    $heap->{socket_wheel}->put("$buf\n");
}



слегка изменяю его.

Код

sub socket_input {
    my ( $heap, $buf ) = @_[ HEAP, ARG0 ];
    $buf =~ s/[\r\n]//gs;
    if ($buf =~ /start/i){
            $kernel->yield( "check_start" );
            if ( $heap->{_Ready} == 0){
                $heap->{socket_wheel}->put("Bla Bla Bla\n");
                print "Error:150\n";
            }
}


код check_start очень простой, он проверяет все ли данные введены или нет. например вот так

Код

sub  check_start{
 my ( $heap ) = @_[ HEAP];
      unless(exists $heap->{_Name}){$heap->{_Ready} = 0}
      $heap->{_Ready} = 1;
}



И что меня напрягает.... 
код после  $kernel->yield( "check_start") выполняется до того как будет создан $heap->{_Ready};

точнее не напрягает, а я понимаю, что это логика POE но может кто подскажет как сделать так, чтобы выполнялся после. На что надо заменить yield?

C уважением shamber

Автор: Ezh 13.11.2006, 00:22
POE не вытесняющая многозадачность. yield только добавляет событие в очередь. Используй call, посмотри post. См описание в POE::Kernel

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)