Wheels (part 2)

By using wheels, we've reduced the amount of code needed for a new server by about 45 lines. We can reduce it just a little more by replacing the ListenAccept wheel with POE::Wheel::SocketFactory. The SocketFactory combines the server socket's creation with the act of accepting new connections from it. It also does a lot more, but we won't touch upon that here.

Rather than rehash the entire program, we'll just replace the _start event's handler. The rest of the program is identical.

sub server_start {
    $_[HEAP]->{server} = POE::Wheel::SocketFactory->new
      ( BindPort => 12345,
        SuccessEvent => "server_accepted",
        FailureEvent => "server_error",
      );
}

That shaves another six lines off the server. We can do much better than that, though.

Here is the full listing:

 1	#!/usr/bin/perl
 2	use warnings;
 3	use strict;
 4	use POE qw(Wheel::SocketFactory Wheel::ReadWrite);
 5	### Start the server session.  Map events to the functions that will
 6	### handle them.  Run all the sessions until they stop, and then exit.
 7	POE::Session->create(
 8	  inline_states => {
 9	    _start          => \&server_start,
10	    server_accepted => \&server_accepted,
11	    server_error    => \&server_error,
12	    client_input    => \&client_input,
13	    client_error    => \&client_error,
14	  }
15	);
16	POE::Kernel->run();
17	exit;
18	### Initialize the newly created server.  Create the server socket,
19	### and then create the wheel to listen on it and accept connections.
20	sub server_start {
21	  $_[HEAP]->{server} = POE::Wheel::SocketFactory->new(
22	    BindPort     => 12345,
23	    SuccessEvent => "server_accepted",
24	    FailureEvent => "server_error",
25	  );
26	}
27	### Handle new connections from the ListenAccept wheel.  Create
28	### ReadWrite wheels to interact with them.  Store them by each
29	### wheel's unique ID so they don't clobber each other.
30	sub server_accepted {
31	  my $client_socket = $_[ARG0];
32	  my $wheel         = POE::Wheel::ReadWrite->new(
33	    Handle     => $client_socket,
34	    InputEvent => "client_input",
35	    ErrorEvent => "client_error",
36	  );
37	  $_[HEAP]->{client}->{$wheel->ID()} = $wheel;
38	}
39	### Handle input from a ReadWrite wheel.  Echo it back to the client.
40	### Each wheel event comes with the wheel's ID, so we can match the
41	### input back to the wheel for resending.
42	sub client_input {
43	  my ($heap, $input, $wheel_id) = @_[HEAP, ARG0, ARG1];
44	  $heap->{client}->{$wheel_id}->put($input);
45	}
46	### Handle client errors.  Delete the ReadWrite wheel associated with
47	### the client.
48	sub client_error {
49	  my ($heap, $wheel_id) = @_[HEAP, ARG3];
50	  delete $heap->{client}->{$wheel_id};
51	}
52	### Handle server socket errors.  Delete the ListenAccept wheel,
53	### shutting down the server.
54	sub server_error {
55	  delete $_[HEAP]->{server};
56	}

Casiano Rodríguez León
Licencia de Creative Commons
Programación Distribuida y Mejora del Rendimiento
por Casiano Rodríguez León is licensed under a Creative Commons Reconocimiento 3.0 Unported License.

Permissions beyond the scope of this license may be available at http://campusvirtual.ull.es/ocw/course/view.php?id=44.
2012-06-19