1# $Id: tcp-poe-raw.pl,v 1.1 2009/01/17 11:29:06 dk Exp $ 2# An echo client-server benchmark. 3 4use warnings; 5use strict; 6 7use Time::HiRes qw(time); 8use POE; 9use IO::Socket::INET; 10 11my $CYCLES = 500; 12my $port = 11211; 13 14# Server. Created before starting the timer, because other benchmarks 15# also do this. 16 17{ 18 POE::Session->create( 19 inline_states => { 20 _start => \&start_server, 21 server_readable => \&accept_connection, 22 client_readable => \&handle_input, 23 }, 24 ); 25 26 sub start_server { 27 my $serv_sock = IO::Socket::INET-> new( 28 Listen => 5, 29 LocalPort => $port, 30 Proto => 'tcp', 31 ReuseAddr => 1, 32 ) or die "listen() error: $!\n"; 33 34 $_[KERNEL]->select_read($serv_sock, "server_readable"); 35 } 36 37 sub accept_connection { 38 my $serv_sock = $_[ARG0]; 39 my $conn = IO::Handle->new(); 40 accept($conn, $serv_sock) or die "accept() error: $!"; 41 $_[KERNEL]->select_read($conn, "client_readable"); 42 $conn->blocking(1); 43 $conn->autoflush(1); 44 } 45 46 sub handle_input { 47 my $conn = $_[ARG0]; 48 my $input = <$conn>; 49 if (defined $input) { 50 print $conn $input; 51 } 52 else { 53 $_[KERNEL]->select_read($conn, undef); 54 } 55 } 56} 57 58my $t = time; 59 60# Client. 61 62{ 63 my $connections = 0; 64 65 POE::Session->create( 66 inline_states => { 67 _start => sub { _make_connection($_[KERNEL]) }, 68 readable => sub { 69 my $sock = $_[ARG0]; 70 $_[KERNEL]->select_read($sock, undef); 71 if ($connections >= $CYCLES) { 72 $_[KERNEL]->stop(); 73 } 74 else { 75 _make_connection($_[KERNEL]); 76 } 77 } 78 }, 79 ); 80 81 # Plain helper function. 82 sub _make_connection { 83 my $kernel = shift; 84 85 $connections++; 86 my $x = IO::Socket::INET-> new( 87 PeerAddr => 'localhost', 88 PeerPort => $port, 89 Proto => 'tcp', 90 ) or die "connect() error: $!$^E\n"; 91 92 $x->autoflush(1); 93 print $x "can write $connections\n"; 94 95 $kernel->select_read($x, "readable"); 96 } 97} 98 99POE::Kernel->run(); 100 101$t = time - $t; 102printf "%.3f sec\n", $t; 103exit; 104