Using POE::Component::Server::TCP
This echo server illustrates recent Server::TCP technology. It requires POE 0.1702 or higher. After starting it, telnet to localhost port 11211, and enter some text.
#!/usr/bin/perl # http://poe.perl.org/?POE_Cookbook/TCP_Servers use warnings; use strict; # Include POE and POE::Component::Server::TCP. use POE qw(Component::Server::TCP); # Start a TCP server. Client input will be logged to the console and # echoed back to the client, one line at a time. POE::Component::Server::TCP->new( Alias => "echo_server", Port => 11211, ClientInput => sub { my ($session, $heap, $input) = @_[SESSION, HEAP, ARG0]; print "Session ", $session->ID(), " got input: $input\n"; $heap->{client}->put($input); } ); # Start the server. $poe_kernel->run(); exit 0;
Using POE::Component::Server::TCP and Filter::SSL
The same as above, but with SSL encryption. Try "openssl s_client -connect localhost:11211", and enter some text.
You need POE::Filter::SSL version 0.20 or later to run this example!
#!/usr/bin/perl # http://poe.perl.org/?POE_Cookbook/TCP_Servers use warnings; use strict; # Include POE, POE::Component::Server::TCP and POE::Filter::SSL (at least 0.17!). use POE qw(Component::Server::TCP Filter::SSL Filter::Line); # Start a TCP server. Client input will be logged to the console and # echoed back to the client, one line at a time. POE::Component::Server::TCP->new( Alias => "echo_server", Port => 11211, # You need to have created certificates for server mode! ClientFilter => ["POE::Filter::SSL", crt => 'server.crt', key => 'server.key'], ClientInput => sub { my ($session, $heap, $input) = @_[SESSION, HEAP, ARG0]; # The following line is needed to do the SSL handshake! print "Session ", $session->ID(), " got input: $input\n"; $heap->{client}->put($input); } ); # Start the server. $poe_kernel->run(); exit 0;
A more advanced example
This echo server illustrates the same Server::TCP technology. This example shows how (and where) more complex processing can be done.
After starting it, telnet to localhost port 11211, and enter some text.
use POE qw(Component::Server::TCP); use strict; use warnings; POE::Session->create( inline_states => { _start => sub { $_[KERNEL]->alias_set('echo_server') }, got_line => sub { my ($kernel, $heap, $postback, $input) = @_[KERNEL, HEAP, ARG0 .. $#_]; # stash the postback on the heap $heap->{postback} = $postback; $kernel->yield(cook_line => $input); }, cook_line => sub { my ($heap, $input) = @_[HEAP, ARG0 .. $#_]; my $postback = $heap->{postback}; # this example can be expanded by doing # something more complex here, SOMETHING, # anyway, other than: my $output = "INPUT: " . $input; $postback->($output); } } ); POE::Component::Server::TCP->new( Port => 11211, # for a more complex application, you can use Filter::Reference to # pass complex data structures as input/output. # ClientFilter => "POE::Filter::Reference", ClientInput => sub { my ($sender, $kernel, $input) = @_[SESSION, KERNEL, ARG0]; $kernel->post( echo_server => got_line => $sender->postback('client_output'), $input ); }, InlineStates => { client_output => sub { my ($heap, $response) = @_[HEAP, ARG1]; $heap->{client}->put($response->[0]) if defined $heap->{client} # that is, if $heap->{client} is still connected } }, ); $poe_kernel->run();
Using SocketFactory and ReadWrite
This echo server creates a listening socket. Telnet to it and type something, pressing enter when you're done. The server will echo it back to you. Sungo
#!/usr/bin/perl # http://poe.perl.org/?POE_Cookbook/TCP_Servers use strict; use warnings; use Socket; use POE qw(Wheel::SocketFactory Wheel::ReadWrite Driver::SysRW Filter::Stream ); ##### # MAIN ##### local $| = 1; our $debug = 1; # be very very noisy our $serverport = 11211; # 'poe' in base10 :P fork and exit unless $debug; POE::Session->create( inline_states => { _start => \&parent_start, _stop => \&parent_stop, socket_birth => \&socket_birth, socket_death => \&socket_death, } ); # $poe_kernel is exported from POE $poe_kernel->run(); exit; #################################### sub parent_start { my $heap = $_[HEAP]; print "= L = Listener birth\n" if $debug; $heap->{listener} = POE::Wheel::SocketFactory->new( BindAddress => '127.0.0.1', BindPort => $serverport, Reuse => 'yes', SuccessEvent => 'socket_birth', FailureEvent => 'socket_death', ); } sub parent_stop { my $heap = $_[HEAP]; delete $heap->{listener}; delete $heap->{session}; print "= L = Listener death\n" if $debug; } ########## # SOCKET # ########## sub socket_birth { my ($socket, $address, $port) = @_[ARG0, ARG1, ARG2]; $address = inet_ntoa($address); print "= S = Socket birth\n" if $debug; POE::Session->create( inline_states => { _start => \&socket_success, _stop => \&socket_death, socket_input => \&socket_input, socket_death => \&socket_death, }, args => [$socket, $address, $port], ); } sub socket_death { my $heap = $_[HEAP]; if ($heap->{socket_wheel}) { print "= S = Socket death\n" if $debug; delete $heap->{socket_wheel}; } } sub socket_success { my ($heap, $kernel, $connected_socket, $address, $port) = @_[HEAP, KERNEL, ARG0, ARG1, ARG2]; print "= I = CONNECTION from $address : $port \n" if $debug; $heap->{socket_wheel} = POE::Wheel::ReadWrite->new( Handle => $connected_socket, Driver => POE::Driver::SysRW->new(), Filter => POE::Filter::Stream->new(), InputEvent => 'socket_input', ErrorEvent => 'socket_death', ); $heap->{socket_wheel}->put("1 Welcome. Say something. I'll say it back.\n\n"); } sub socket_input { my ($heap, $buf) = @_[HEAP, ARG0]; $buf =~ s/[\r\n]//gs; $heap->{socket_wheel}->put("$buf\n"); }