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