First Steps with AnyEvent

I’ve been playing around with Plack and Twiggy recently and that motivated me to take a look at AnyEvent, the eventing library that Twiggy is built upon.

Now, it seems to me that AnyEvent is useful in a similar problem-space to POE (or Coro, on Unix at least). POE has more documentation but AnyEvent can actually use a couple of Event Loops that were implemented in C: EV and libevent which is the backbone of the hugely successful memcached. Sounds good to me.

As usual, first things first. How do you make a simple TCP server? I took a look at how Twiggy does it – the code is available in Twiggy::Server. I won’t need everything in there of course.

The Preamble

I like the way that Twiggy sets a constant called DEBUG from an environment variable. Now I can call the script like this: $ SERVER_DEBUG=1 ./ae.pl and get debugging output.

Basic Perl Objects

The watch variables only watch while they are in scope. If we have a simple object, we can dump them into the underlying blessed hash reference to keep ’em in scope. I’m lamenting the non-standardness of Moose here, but that’s another post.

Bottom-up or Top-down I’m never quite sure how to present my code. Hmmm…

AnyEvent::tcp_server

So, we’re assuming here that a server object will be called (with my $server Server->new()=) and then we will call $server->start_listen(...).

The example tcp_server call in the AnyEvent::Socket documentation rather unhelpfully demonstrates closing the socket the moment it has connected with a The internet is full, $host:$port. Go away! message. Oh well, maybe my examples are equally flawed. Thank goodness for Twiggy.

prepare_handler just logs a basic message on start-up. The accept handler returns a closure to maintain access to $self. The closure sets the socket options and then creates a watcher using watch_socket.

AnyEvent IO watcher

The watcher is setup to echo whatever it received, back to the sender. If it receives EOF (sent when a telnet client hits CTRL-D), then it terminates the connection.

Now, I didn’t manage to get this working immediately. If the watcher goes out of scope, it doesn’t end up watching anything. And I originally omitted the undef $headers_io_watcher statements. As the closure wasn’t referring to the watcher variable, it went out of scope immediately. Adding them added a reference which stopped that happening. Nice, if a little subtle.

It does not accept multiple connections when I run it. It closes the current connection and then accepts the new one when another client connects to it.
any ideas? or any pointers to tutorials on AnyEvent?

Sorry guys, my mistake. It does accept multiple connections. Trick is not to overwirte or outscope $headers_io_watcher (as mentioned in the original post).
What I was trying to do was to save the $headers_io_watcher into $self and add a ‘cleanup’ function which goes and undefines each $headers_io_watcher, thus closing the connection to each client before shutting down. So now I have a hash in $self with all the $headers_io_watcher past and present. when a new connection arrives I add the new $headers_io_watcher into the hash and remove any which are undef – i.e. connection closed. At the end when a cleanup function is called, it goes through this hash and undef’s each value.

Still pointers to AnyEvent tutorials are needed. Thanks for the post, it was most useful for me.

I’ve just started learning AnyEvent, this event-based-programming stuff is new to me. I’m liking the concept though. Could you recommend some sources to learn it well? I have gone through the AnyEvent::Intro and your article.