avo has asked for the wisdom of the Perl Monks concerning the following question:

Good day Monks,

I have recently downloaded POE: POE Cookbook/TCP Port Redirection With Components. I changed the outgoing port of the client side process to be port 80 on another IP. Regardless when I try and open port 1110 my poe program gives an error as follows:
Can't locate object method "put" via package "POE::Wheel::SocketFactory" at portforward.pl line 76.

Herewith the code:
#!/usr/bin/perl use warnings; use strict; use POE qw(Component::Server::TCP Component::Client::TCP); # Spawn the forwarder server on port 1110. When new connections # arrive, spawn clients to connect them to their destination. POE::Component::Server::TCP->new( Port => 1110, ClientConnected => sub { my ( $heap, $session ) = @_[ HEAP, SESSION ]; #logevent( 'server got connection', $session ); spawn_client_side(); }, ClientInput => sub { my ( $kernel, $session, $heap, $input ) = @_[ KERNEL, SESSION, + HEAP, ARG0 ]; #logevent( 'server got input', $session, $input ); $kernel->post( $heap->{client_id} => send_stuff => $input ); }, ClientDisconnected => sub { my ( $kernel, $session, $heap ) = @_[ KERNEL, SESSION, HEAP ]; #logevent( 'server got disconnect', $session ); $kernel->post( $heap->{client_id} => "shutdown" ); }, InlineStates => { send_stuff => sub { my ( $heap, $stuff ) = @_[ HEAP, ARG0 ]; #logevent( "sending to server", $_[SESSION] ); $heap->{client}->put($stuff); }, _child => sub { my ( $heap, $child_op, $child ) = @_[ HEAP, ARG0, ARG1 ]; if ( $child_op eq "create" ) { $heap->{client_id} = $child->ID; } }, }, ); sub spawn_client_side { POE::Component::Client::TCP->new( RemoteAddress => '192.168.0.200', RemotePort => 81, Started => sub { $_[HEAP]->{server_id} = $_[SENDER]->ID; }, Connected => sub { my ( $heap, $session ) = @_[ HEAP, SESSION ]; #logevent( 'client connected', $session ); }, ServerInput => sub { my ( $kernel, $heap, $session, $input ) = @_[ KERNEL, HEAP +, SESSION, ARG0 ]; #logevent( 'client got input', $session, $input ); $kernel->post( $heap->{server_id} => send_stuff => $input +); }, Disconnected => sub { my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSIO +N ]; #logevent( 'client disconnected', $session ); $kernel->post( $heap->{server_id} => 'shutdown' ); }, InlineStates => { send_stuff => sub { my ( $heap, $stuff ) = @_[ HEAP, ARG0 ]; #logevent( "sending to client", $_[SESSION] ); $heap->{server}->put($stuff); }, }, ); } sub logevent { my ( $state, $session, $arg ) = @_; my $id = $session->ID(); print "session $id $state "; print ": $arg" if ( defined $arg ); print "\n"; } warn 'running'; $poe_kernel->run(); exit 0;

Replies are listed 'Best First'.
Re: Problem with POE and Port Forwarding
by moritz (Cardinal) on May 22, 2008 at 09:16 UTC
    How did you manage to even compile your code? I tried it with perl 5.8.8 and POE 0.3502-1 as well as on perl 5.10.0 and POE 1.0001-1, and with both combinations I get
    Bareword "ARG" not allowed while "strict subs" in use at foo.pl line 2 +0. Execution of foo.pl aborted due to compilation errors.

    Update: how embarrassing, shmem is right - it was a copy-paste error on my side. With the correct code I can reproduce the problem on both platforms mentioned above.

    POE::Wheel::SocketFactory doesn't have a put method. It seems you are expecting a different object (a socket, no socket factory). My POE-fu isn't good enough to suggest a solution, though.

      Bareword "ARG" not allowed while "strict subs" in use at foo.pl line 20.

      Copy-paste error. That word on line 20 is ARG0, which is a constant sub invocation (returns 10).

      Use the download link...

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Problem with POE and Port Forwarding
by bingos (Vicar) on May 24, 2008 at 07:53 UTC

    Having tested this out, I believe that either: the RemoteAddress or RemotePort settings to the POE::Component::Client::TCP constructor are wrong; or: the POE::Component::Client::TCP part is taking a little while to establish a connection. Either way we can check the value of $heap->{connected} in the client session to see if we are connected yet.

    Here's an altered version that shouldn't bail out if the client component fails to establish a connection.

    #!/usr/bin/perl use warnings; use strict; use POE qw(Component::Server::TCP Component::Client::TCP); # Spawn the forwarder server on port 1110. When new connections # arrive, spawn clients to connect them to their destination. POE::Component::Server::TCP->new( Port => 1110, ClientConnected => sub { my ( $heap, $session ) = @_[ HEAP, SESSION ]; #logevent( 'server got connection', $session ); spawn_client_side(); }, ClientInput => sub { my ( $kernel, $session, $heap, $input ) = @_[ KERNEL, SESSION, + HEAP, ARG0 ]; #logevent( 'server got input', $session, $input ); $kernel->post( $heap->{client_id} => send_stuff => $input ); }, ClientDisconnected => sub { my ( $kernel, $session, $heap ) = @_[ KERNEL, SESSION, HEAP ]; #logevent( 'server got disconnect', $session ); $kernel->post( $heap->{client_id} => "shutdown" ); }, InlineStates => { send_stuff => sub { my ( $heap, $stuff ) = @_[ HEAP, ARG0 ]; #logevent( "sending to server", $_[SESSION] ); $heap->{client}->put($stuff); }, _child => sub { my ( $heap, $child_op, $child ) = @_[ HEAP, ARG0, ARG1 ]; if ( $child_op eq "create" ) { $heap->{client_id} = $child->ID; } }, }, ); sub spawn_client_side { POE::Component::Client::TCP->new( RemoteAddress => '192.168.0.200', RemotePort => 81, Started => sub { $_[HEAP]->{server_id} = $_[SENDER]->ID; }, Connected => sub { my ( $heap, $session ) = @_[ HEAP, SESSION ]; #logevent( 'client connected', $session ); }, ConnectError => sub { my ( $syscall, $errnum, $errstr ) = @_[ ARG0 .. ARG2 ]; warn "$syscall $errnum $errstr\n"; }, ServerInput => sub { my ( $kernel, $heap, $session, $input ) = @_[ KERNEL, HEAP +, SESSION, ARG0 ]; #logevent( 'client got input', $session, $input ); $kernel->post( $heap->{server_id} => send_stuff => $input +); }, Disconnected => sub { my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSIO +N ]; #logevent( 'client disconnected', $session ); $kernel->post( $heap->{server_id} => 'shutdown' ); }, InlineStates => { send_stuff => sub { my ( $heap, $stuff ) = @_[ HEAP, ARG0 ]; #logevent( "sending to client", $_[SESSION] ); $heap->{server}->put($stuff) if $heap->{connected}; }, }, ); } sub logevent { my ( $state, $session, $arg ) = @_; my $id = $session->ID(); print "session $id $state "; print ": $arg" if ( defined $arg ); print "\n"; } warn 'running'; $poe_kernel->run(); exit 0;