AnyEvent::Socket で簡単な echo サーバを書く

AnyEvent の勉強がてら、簡単な echo サーバを書いてみた。只の echo サーバではつまらないので返事をする度に数値をインクリメントして付与するようにしてみる。

#!/usr/local/bin/perl

use warnings;
use strict;
use AnyEvent;
use AnyEvent::Socket;

tcp_server undef, 12345, sub {
    my( $fh, $host, $port ) = @_;
    warn "connect from $host:$port\n";
    add_client($fh);
};

sub add_client {
    my $fh = shift;
    my $i  = 0;
    my $poller; $poller = AnyEvent->io(
        fh   => $fh,
        poll => 'r',
        cb   => sub {
            my $r = sysread $fh, my $buf, 1024;
            # got EOF
            if ( 0 == $r ) {
                undef $poller;
                return;
            }
            $i++;
            syswrite $fh, "($i):$buf";
        }
    );
}

AnyEvent->condvar->recv;

サーバを起動して、繋いでみる。

% telnet localhost 12345
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
aaa
(1):aaa
bbb
(2):bbb
ccc
(3):ccc
ddd
(4):ddd
eee
(5):eee
^]close
telnet> close
Connection closed.

もう一回

% telnet localhost 12345
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
aaa
(1):aaa
ddd
(2):ddd
rrr
(3):rrr
qqq
(4):qqq
^]close
telnet> close
Connection closed.

AnyEvent のコード量の少なさと書きやすさは異常かも。