Skip to content

Instantly share code, notes, and snippets.

@yowcow
Created November 20, 2014 13:26
Show Gist options
  • Save yowcow/fdbacb294bee5e877731 to your computer and use it in GitHub Desktop.
Save yowcow/fdbacb294bee5e877731 to your computer and use it in GitHub Desktop.
Simple non-blocking server
use common::sense;
use AnyEvent;
use AnyEvent::Socket;
use AnyEvent::Handle;
use Data::Dumper;
my $cv = AnyEvent->condvar;
my %clients;
my %names;
tcp_server undef, 5001, sub {
my ( $fh, $host, $port ) = @_;
print "Connection established: ${host}:${port}\n";
my $handle = AnyEvent::Handle->new( fh => $fh );
my $broadcast_cb = sub {
my ( $fileno, $line ) = @_;
$clients{$_}->{handle}->push_write($line)
for grep { $_ ne $fileno } keys %clients;
};
my $handle_disconnect_cb = sub {
my $h = shift;
my $fileno = fileno( $h->fh );
if ( my $client = delete $clients{ fileno( $h->fh ) } ) {
my $name = $client->{name};
$broadcast_cb->( $fileno, "-> ${name} has left.\n", );
}
$h->destroy;
};
my $handle_connect_cb = sub {
my $h = shift;
my $fileno = fileno( $h->fh );
my $name = $clients{$fileno}->{name};
$h->push_write("-> Welcome, ${name}!\n");
$broadcast_cb->( $fileno, "-> ${name} has joined.\n" );
};
my $handle_read_cb = sub {
my ( $h, $line ) = @_;
my $fileno = fileno( $h->fh );
my $client = $clients{$fileno};
if ( !defined $client->{name} ) {
if ( defined $names{$line} ) {
$h->push_write("-> ${line} is taken, try again: ");
}
else {
$names{$line} = 1;
$client->{name} = $line;
$handle_connect_cb->( $h, $client->{name} );
}
}
else {
$broadcast_cb->( $fileno, $client->{name} . ": ${line}\n" );
}
};
$handle->on_error($handle_disconnect_cb);
$handle->on_eof($handle_disconnect_cb);
$handle->on_read( sub { $_[0]->push_read( line => $handle_read_cb ) } );
#$handle->on_drain(sub { });
$handle->push_write("-> Your name is?: ");
$clients{ fileno($fh) } = {
name => undef,
handle => $handle,
};
};
$cv->recv;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment