perl poe tcp服务器处理多个客户端

时间:2013-12-08 17:44:06

标签: perl tcp

您好我有一个POE TCP服务器,它需要处理多个客户端。新客户端连接并请求服务器“开始发送数据”,服务器将开始发送数据,当客户端请求服务器“停止发送数据”时服务器将停止发送数据。这应该发生在多个客户端。我尝试过但它只处理一个客户端。以下是代码,请帮我解决这个问题?

use warnings;
use strict;
use POE;
use POE::Component::Server::TCP;
use Data::Dumper;

POE::Component::Server::TCP->new(
    Alias              => "server",
    Port               => 2000,
    ClientFilter => 'POE::Filter::Stream',
    ClientArgs => [
        $ARGV[0]
    ],
    Started => sub {
        my ($session, $heap) = @_[SESSION, HEAP];
        print STDERR "Server started\n";
    },
    ClientConnected    => sub {
        my($session, $kernel, $heap) = @_[SESSION, KERNEL, HEAP];
        $kernel->alias_set('Downloader');
        $heap->{current_state} = "waiting for command";
        $heap->{START} = 0;
        $heap->{STOP} = 0;
        $heap->{isStopPending} = 0;
        $heap->{sessionID} = $_[SESSION]->ID;
    },
    ClientInput        => sub {
        my ($heap, $kernel, $session, $input) = @_[HEAP, KERNEL, SESSION, ARG0];
        $heap->{input} .= $input;
        process_data ($heap,$session,$kernel);
    },

    InlineStates       => {
        StartSending => sub {
            my ($heap, $kernel, $session) = @_[HEAP, KERNEL, SESSION];
            $kernel->post('Downloader', 'OnSending');
        },
        OnSending => sub {
            my ($heap, $kernel, $session) = @_[HEAP, KERNEL, SESSION];
            if ($heap->{isStopPending} != 0 ) {
                  $heap->{isStopPending} = 0;
                  print STDERR "Stopped to session $heap->{sessionID}...\n";
                  return;
            }else {
                  print STDERR "Sending to SessionID: $heap->{sessionID}\n";
                  read_file ($heap);
                  $heap->{client}->put($heap->{data});
                  $heap->{data} = '';
                  $kernel->alarm(OnSending=> time() + 1, 0);
            }
         },
        StopWasRequested => sub {
             my ($heap, $kernel, $session) = @_[HEAP, KERNEL, SESSION];
             $heap->{isStopPending} = 1;
             print STDERR "Stop was requested\n";
        },
    },
);

sub process_data {
    my ($heap, $session, $kernel) = @_;
    if ($heap->{current_state} eq "waiting for command") {
        process_Command ($heap);
        if ($heap->{command} eq "START") {
            $heap->{current_state} = "waiting for command";
            Start ($heap, $kernel, $session);
        } elsif ($heap->{command} eq "STOP") {
            $heap->{current_state} = "waiting for command";
            Stop ($heap, $kernel, $session);
        }
    }
    return;
}
sub process_Command {
    my ($heap) = @_;
    my $input = $heap->{input};
    my $length = length($input);
    $input =~ s/^(.{$length})//;
    $heap->{input} = $input;
    $heap->{command} = $1;
    return;
}
sub Start {
    my ($heap, $kernel, $session) = @_;
    return if ($heap->{START} == 1);
    $heap->{START} = 1;
    $heap->{STOP} = 0;
    $kernel->yield('StartSending');
}

sub Stop {
    my ($heap, $kernel, $session) = @_;
    $heap->{STOP} = 1;
    $heap->{START} = 0;
    print STDERR "Stop...\n";
    $kernel->post($heap->{sessionID}=>'StopWasRequested');
}

sub read_file {
    my ($heap) = @_;
    my $filesize = -s "0001.out";
    open (RF, "<0001.out") or die "could not open file";
    binmode (RF);
    read (RF, my $data, $filesize);
    close (RF);
    $heap->{data} = $data;
    return;
}

$poe_kernel->run();
exit 0;

1 个答案:

答案 0 :(得分:0)

在ClientConnected回调中,$kernel->alias_set('Downloader');语句适用于第一个连接客户端(会话),后续客户端(会话)不应设置相同的别名“Downloader”。在InsliStates的'StartSending'回调中,post destination是'Downloader',以便服务器将数据发送到第一个连接客户端。要将数据发送到多个客户端,请使用SESSION_ID作为目标,而不是ALIAS,在本例中为“Downloader”。所以替换:

$kernel->post('Downloader', 'OnSending');

通过

$kernel->post($_[SESSION]->ID=>'OnSending');

在Inlinestates的“StartSending”回调中。所以现在工作正常。