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
