Let me start with a "Happy New Year!" to all perlmonks.
Your debugging print tip did the trick: it showed that $wheel_id (ARG1) is empty.
POE::Wheel::SocketFactory uses ARG3 not ARG1 for the wheels id.
Because of this I had to change the way the wheel id is passed from subroutine 'start' to 'factory_succes' to 'client_input'.
I used the HEAP variable (is this the correct way?)
Problem is now that it works with one telnet session.
As soon a second telnet session is started the script breaks connection with telnet session one.
As far I can see this is because POE::Wheel::SocketFactory reuses the wheel id from telnet session one for telnet session two.
I don't know why it does this because according to the documentation it should start a new 'wheel'.
Can somebody help me with this problem?
In the second part of the article concurrent telnet sessions work by using POE::Component::Server:TCP.
But I'm a bit stubborn and want to get the basics right before moving on...
Here is the code I modified:
#!/usr/bin/perl -w
use warnings;
use strict;
use Carp qw(carp croak);
use POE qw( Wheel::SocketFactory Driver::SysRW Wheel::ReadWrite);
{ package POE::Filter::SimpleQueryString;
use Carp qw(carp croak);
sub new {
my $class = shift;
my $self = bless {}, $class;
return $self;
}
sub get {
my $self = shift;
my $buffer = shift;
my @chunks;
foreach my $record (@$buffer) {
$record =~ s/\x0d\x0a$//;
my @pairs = split(/&/, $record);
my %chunk;
foreach my $pair (@pairs) {
my ($key, $value) = split(/=/, $pair, 2);
if(defined $chunk{$key}) {
if(ref $chunk{$key} eq 'ARRAY') {
push @{ $chunk{$key} }, $value;
} else {
$chunk{$key} = [ $chunk{$key}, $value ],
}
} else {
$chunk{$key} = $value;
}
}
push @chunks, \%chunk;
}
return \@chunks;
}
sub put {
my $self = shift;
my $records = shift;
print "$self\n$records\n";
my @raw;
foreach my $record (@$records) {
my @chunks;
foreach my $key (sort keys %$record) {
if(ref $record->{$key}) {
if(ref $record->{$key} eq 'ARRAY') {
foreach my $value ( @{ $record->{$key} } ) {
push @chunks, $key."=".$value;
}
} else {
carp __PACKAGE__." cannot handle data of type
".ref $record->{$key};
}
} else {
push @chunks, $key."=".$record->{$key};
}
}
push @raw, join('&',@chunks)."\x0d\x0a";
}
return \@raw;
}
}
sub start {
$_[HEAP]->{factory} = POE::Wheel::SocketFactory->new( BindAddress
+ => '127.0.0.1',
BindPort
+ => '31337',
SuccessEvent
+ => 'factory_success',
FailureEvent
+ => 'fatal_error',
SocketProtocol
+ => 'tcp',
Reuse
+ => 'on',
);
}
sub factory_success {
my ($handle, $wheel_id) = @_[ARG0, ARG3];
my $temp_rw_id = POE::Wheel::ReadWrite->new( Handle => $handle,
Driver => POE::Dri
+ver::SysRW->new(),
Filter => POE::Fil
+ter::SimpleQueryString->new(),
InputEvent => 'client_
+input',
);
$_[HEAP]->{clients}->{$wheel_id} = $temp_rw_id;
+
$_[HEAP]->{current_client}->{$temp_rw_id->ID} = $wheel_id;
print "factory_success called, creating wheel $wheel_id for handle $
+handle | ( ".$temp_rw_id->ID." )\n";
}
sub client_input {
my ($input, $wheel_id) = @_[ARG0, ARG1];
my $factory_id = $_[HEAP]->{current_client}->{$wheel_id};
use Data::Dumper;
print Dumper $input;
print "wheel_id is: $wheel_id\n";
print "factory_id is: $factory_id\n";
$_[HEAP]->{clients}->{$factory_id}->put($input);
}
POE::Session->create( inline_states => { _start => \&start,
factory_success => \&factory_
+success,
client_input => \&client_i
+nput,
client_error => \&client_e
+rror,
fatal_error => sub { die
+"A fatal error occurred" },
_stop => sub {},
},
);
POE::Kernel->run();
PS I mailed the editors of perl.com and asked them to fix the download link in the article.