navalned has asked for the wisdom of the Perl Monks concerning the following question:

I have the following code that I believe should function as an echo server.
#!/usr/bin/env perl use strict ; use warnings ; use AnyEvent ; use AnyEvent::Handle ; use AnyEvent::Socket ; my $main = AnyEvent->condvar(); tcp_server undef, undef, sub { my ($fh, $host, $port) = @_; my $handle; $handle = AnyEvent::Handle->new( fh => $fh, on_error => sub { my ($hdl, $fatal, $msg) = @_; AE::log error => $msg; $hdl->destroy(); }, on_eof => sub { my ($hdl) = @_; $hdl->destroy(); }, on_read => sub { my ($hdl) = @_; $hdl->push_read(line => sub { my ($hdl, $line) = @_; if ($line =~ m/quit/i) { $hdl->push_write("goodbye\n"); $hdl->destroy(); } $hdl->push_write($line); }); } ); $handle->push_write("Hello $host:$port\n"); }, sub { my ($fh, $thishost, $thisport) = @_; print STDERR "$thishost:$thisport\n"; }; $main->recv();
However, when I netcat into the server. I see the greeting and the server immediately closes the connection. I'm probably missing something simple, but not sure what. Thanks!

Replies are listed 'Best First'.
Re: AnyEvent tcp_server not working
by kikuchiyo (Friar) on Apr 03, 2020 at 22:21 UTC

    The problem is that the  my $handle variable is private to the callback sub, and is not referenced anywhere else. So when that sub returns (immediately after push_writing your "Hello" message), it will be destroyed, and with it, your connection.

    A solution is including a reference to it in one of AE::Handle's callbacks, e.g.:

    on_error => sub { my ($hdl, $fatal, $msg) = @_; AE::log error => $msg; $hdl->destroy(); undef $handle; # <------ },

    This way, the callback sub closes over the variable, so its reference count will be nonzero when the sub returns and thus your connection will stay alive.

      That did it. I need to go back through the manuals. I don't think I read anything that mentioned this. Thanks!
Re: AnyEvent tcp_server not working
by Anonymous Monk on Apr 03, 2020 at 21:37 UTC


    None of your callback have diagnostic information

    For example

    use Time::HiRes; warn time, 'on_error', "\n";