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

Hi all, I am trying to write a port forward using POE.
Assume I want to forward connection from port 10086 to port 80, so telnet localhost 10086 can get the access to the web server.
I can use 'GET /' to get the index page of the web, and then the server will close my connection to 80, but I still connected to 10086. So my question is, how can I detect the server has closed my connection so that I can close the client?
my code for this forwarder can be found at here Update: Here is the code
#!/usr/bin/perl use strict; use warnings; use Smart::Comments; use POE qw/Wheel::SocketFactory Wheel::ReadWrite Filter::Stream Driver::SysR +W/; POE::Session->create( inline_states => { _start => \&_create_socket, on_client_accept => \&client_accept, on_server_error => \&server_error, on_client_error => \&client_error, }, ); POE::Kernel->run; sub _create_socket { my ($kernel, $heap) = @_[KERNEL, HEAP]; $heap->{server} = POE::Wheel::SocketFactory->new( BindPort => '10086', Reuse => 1, SuccessEvent => 'on_client_accept', FailureEvent => 'on_server_error', ); } sub client_accept { my ($client, $heap) = @_[ARG0, HEAP]; #create new session handle remote host POE::Session->create( inline_states => { _start => \&connect_to_remote, on_remote_connect => \&remote_connected, on_remote_fail => \&remote_fail, forward_out => \&forward_out, forward_in => \&forward_in, remote_flush => \&remote_flush, }, args => [$client], ); } sub connect_to_remote { my ($heap, $local_socket) = @_[HEAP, ARG0]; #create socket connect to port we want to forward my $remote = POE::Wheel::SocketFactory->new( RemoteAddress => 'localhost', RemotePort => '80', SuccessEvent => 'on_remote_connect', FailureEvent => 'on_remote_fail', ); $heap->{remote} = $remote; # create wheel to read the local socket $heap->{local_wheel} = POE::Wheel::ReadWrite->new( Handle => $local_socket, Filter => POE::Filter::Stream->new(), InputEvent => 'forward_out', ); $heap->{local_socket} = $local_socket; } sub remote_connected { my ($heap, $socket) = @_[HEAP, ARG0]; my $wheel = POE::Wheel::ReadWrite->new( Handle => $socket, Driver => POE::Driver::SysRW->new(), Filter => POE::Filter::Stream->new(), InputEvent => 'forward_in', #FlushedEvent => 'remote_flush', ); $heap->{remote_wheel} = $wheel; } sub server_erorr { my ($operation, $errnum, $errstr) = @_[ARG0, ARG1, ARG2]; warn "server opeartion: $operation failed with number: $errnum\n\t string: $errstr"; delete $_[HEAP]{server}; } sub client_error { my $id = $_[ARG3]; delete $_[HEAP]{client}{$id}{x}; } sub forward_out { my ($heap, $data, $wheel) = @_[HEAP, ARG0]; $heap->{remote_wheel}->put($data); } sub forward_in { my ($heap, $data) = @_[HEAP, ARG0]; $heap->{local_wheel}->put($data); $_[KERNEL]->yield('remote_flush') } sub port_fail { print "failed to connnect to port\n"; } sub remote_fail { delete $_[HEAP]->{remote}; } sub remote_flush { my $heap = $_[HEAP]; print "remote flushed\n"; print "remote have no remote\n" if !exists $heap->{remote}; if (!$heap->{remote_wheel}->get_driver_out_octets) { $heap->{remote_wheel}->flush; delete $heap->{remote}; $heap->{local_wheel}->put("remote server Disconnected\n"); #delete $heap->{local_wheel}; $heap->{local_socket}->flush ; close $heap->{local_socket}; } }

Replies are listed 'Best First'.
Re: POE: How can I detect server closed my connection?
by MidLifeXis (Monsignor) on Jul 19, 2011 at 12:49 UTC

    Please update (or post a reply) your node (include a note that you updated it) with the code from the gist. We try to keep code being commented on local to Perl Monks, so that when the external link goes away, it will not cause the thread on Perl Monks to become less valuable.

    --MidLifeXis

Re: POE: How can I detect server closed my connection?
by rcaputo (Chaplain) on Jul 19, 2011 at 15:07 UTC

    You are not handling ErrorEvent from your POE::Wheel::ReadWrite objects. EOF from the remote endpoint is reported as read error 0. Other errors may occur, such as ECONNRESET (Connection reset by peer).

    Sorry we missed you on irc.perl.org #poe. It was 5:45AM, and I was asleep. :)

      Apparently we are in the different time zone~~~ it was afternoon at that time for me :)

      ErrorEvent is what I want, thanks for the help.

Re: POE: How can I detect server closed my connection?
by zentara (Cardinal) on Jul 19, 2011 at 13:01 UTC
    From your code, you seem to have a $socket variable. Try the connected method of IO::Socket.
    if ($socket->connected) { } #or if ! ($socket->connected) { }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: POE: How can I detect server closed my connection?
by Anonymous Monk on Jul 19, 2011 at 12:49 UTC
    whichever POE whatever you're using :) will/should generate a close event for which you can register a handler (client_disconnected or whatever)

    There should also be a default event for which you can register a handler

    :)

      I just did not find such a event for POE::Wheel::SocketFactory