Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

Creating A Single Threaded Server with AnyEvent

by mobiusinversion (Beadle)
on Nov 06, 2012 at 22:50 UTC ( #1002594=perlquestion: print w/replies, xml ) Need Help??
mobiusinversion has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, Im working on creating a local service to listen on localhost and provide a basic call and response type interface. What I'd like to start with is a baby server that you can connect to over telnet and echoes what it receives. I've heard AnyEvent is great for this, but the documentation for AnyEvent::Socket does not give a very good example how to do this. I'd like to build this with AnyEvent, AnyEvent::Socket and AnyEvent::Handle. Right now the little server code looks like this:
#!/usr/bin/env perl use AnyEvent; use AnyEvent::Handle; use AnyEvent::Socket; my $cv = AnyEvent->condvar; my $host = ''; my $port = 44244; tcp_server($host, $port, sub { my($fh) = @_; my $cv = AnyEvent->condvar; my $handle; $handle = AnyEvent::Handle->new( fh => $fh, poll => "r", on_read => sub { my($self) = @_; print "Received: " . $self->rbuf . "\n"; $cv->send; } ); $cv->recv; }); print "Listening on $host\n"; $cv->wait;
This doesn't work and also if I telnet to localhost:44244 I get this:
EV: error in callback (ignoring): AnyEvent::CondVar: recursive blockin +g wait attempted at line 29.
I think if I understand how to make a mini, single threaded server that simply prints out whatever its given and then waits for more input, I could take it a lot further from there. Any ideas?

Replies are listed 'Best First'.
Re: Creating A Single Threaded Server with AnyEvent
by Tanktalus (Canon) on Nov 07, 2012 at 00:31 UTC

    (a) We prefer cross-posting to be mentioned. It's just polite. (Many people watch both sites, so they don't need to waste time reading both posts.)

    (b) You're not getting better answers on stackoverflow, are you sure your doubts are for perlmonks? (IMO, you shouldn't really post where you have doubts anyway, both sites are valid.)

    (c) You're blocking inside a callback. That's not allowed. There are a few ways to handle this. My preference is to launch a Coro thread from within the tcp_server callback. But without Coro, something like this might be what you're looking for:

    #!/usr/bin/env perl5.16.2 use AnyEvent; use AnyEvent::Handle; use AnyEvent::Socket; my $cv = AE::cv; my $host = ''; my $port = 44244; my %connections; tcp_server( $host, $port, sub { my ($fh) = @_; print "Connected...\n"; my $handle; $handle = AnyEvent::Handle->new( fh => $fh, poll => 'r', on_read => sub { my ($self) = @_; print "Received: " +. $self->rbuf . "\n"; }, on_eof => sub { my ($hdl) = @_; $hdl->destroy(); }, ); $connections{$handle} = $handle; # keep it alive. return; }); print "Listening on $host\n"; $cv->recv;
    Note that I'm only waiting on one condvar. And I'm storing the handles to keep the AnyEvent::Handle objects alive longer. Work to clean up the $self->rbuf is left as an excersise for the reader :-)

    Update: cross-posted answer, too

Re: Creating A Single Threaded Server with AnyEvent
by Kenosis (Priest) on Nov 06, 2012 at 23:12 UTC

    Cross-posted on stackoverflow.

    "It is considered polite to inform about crossposting so people not attending both sites do not waste their time solving a problem already closed at the other end of the internet."

      Thats not constructive or useful. I have / had my doubts of this getting answered on Perlmonks. Mostly because when you ask a perl person X they usually say, oh look, if you just do Y its better, usually for the sake of answering quickly. Ie your argument about time wasted makes no sense. Eg above, I asked how to accomplish this with AnyEvent, not POE. Do you have an answer in the slightest or are you just trolling?

        My posting's constructiveness was its sharing of a cross-posting courtesy with you. Please see the following: Cross-posting Policy?

Re: Creating A Single Threaded Server with AnyEvent
by james2vegas (Chaplain) on Nov 07, 2012 at 08:57 UTC
    You are recursively calling $cv->recv, instead you should, when you create your new condvar, associate a callback which will be called when you send on your $cv
Re: Creating A Single Threaded Server with AnyEvent
by rcaputo (Chaplain) on Nov 06, 2012 at 23:03 UTC
      Can you tell me a way to do this with the modules mentioned above?

        Sorry, I don't know the direct answer to your question, and I'm reluctant to pretend to be an expert in a module I don't know well. "There Is More Than One Way To Do It" is a part of Perl culture, so I thought I'd offer some equivalents that I'm more proficient in.

Re: Creating A Single Threaded Server with AnyEvent
by zentara (Archbishop) on Nov 08, 2012 at 11:09 UTC

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1002594]
Approved by kcott
marioroy just logged in to say that MCE::Hobo has passed testing and therefore will continue to run like threads but have managed capabilities similar to Parallel:: ForkManager. It allows multiple managed instances to run simultaneously. Zero limitations.
marioroy it's taken a long time to make this possible.
marioroy will post demonstrations after release

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (8)
As of 2017-07-28 19:47 GMT
Find Nodes?
    Voting Booth?
    I came, I saw, I ...

    Results (434 votes). Check out past polls.