2013-12-08 79 views
1

嗨,我有一个POE TCP服务器,它需要处理多个客户端。新客户端连接并请求服务器'开始发送数据',服务器将开始发送数据,当客户端请求服务器'停止发送数据'时,服务器将停止发送数据。这应该发生在多个客户端上。我尝试过,但它只处理一个客户端。下面是它的代码请帮助我如何解决这个问题?perl 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; 

回答

0

在ClientConnected回调,$kernel->alias_set('Downloader');声明适用于第一个客户端连接(会话),后续的客户端(会话)不应该设定相同的别名“下载”。在InsliState的'StartSending'回调中,发布目标是'Downloader',以便服务器将数据发送到第一个连接客户端。要将数据发送到多个客户端,请使用SESSION_ID作为目的地,而不是此处的“下载器”的ALIAS。所以更换:

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

通过

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

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