http://qs321.pair.com?node_id=490609

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

I've been trying to wrap my head around POE. I have a lengthy script that sees whether it can open a socket on various ports on various machines (over 100 connecctions all told). Actually the script is short, it just takes a long time to run, since everything is done serially.

It's just too slow... so I finally found some time to investigate POE, and I have the following code:

use strict; use POE; use POE::Component::Client::TCP; my $task = [ { name => 'www.example.com', proto => 'tcp', port => 80 }, { name => 'smtp.example.com', proto => 'tcp', port => 25 }, { name => 'ns.example.com', proto => 'udp', port => 53 }, ]; for my $t( @$task ) { next if $t->{proto} ne 'tcp'; POE::Component::Client::TCP->new( RemoteAddress => $t->{host}, RemotePort => $t->{port}, Connected => sub { print "$t->{host}:$t->{proto}:$t->{port} up\n"; $poe_kernel->yield( 'shutdown' ); }, ConnectError => sub { print "$t->{host}:$t->{proto}:$t->{por +t} down\n" }, ConnectTimeout => 2, ServerInput => sub { }, ); } $poe_kernel->run();

This actually works quite well. It takes less than a second to run if all services are up, and a smidgen more than two seconds if a service is down. Much better than the 13 seconds the old script takes.

It does, however, have a major flaw, in that it doesn't know how to deal with UDP. I use the POE::Component::Client::TCP module to deal with TCP protocols, but there's no such thing as POE::Component::Client::UDP, and I don't know how to go about using the POE building blocks to make something that would work. All I need is a true/false result to the question "could I open a socket".

The other flaw that I don't like is the klugey empty ServerInput callback. It's never called, but the object cannot be constructed if this key/value pair is missing. This may mean that I'm using POE::Component::Client::TCP for a purpose for which it was not designed. Which in turn may mean that I'm paying for a lot of startup overhead that may be avoided by using some other technique. Again, just like for UDP, I'm only interested in a yes/no answer.

I also suspect that both of these flaws are probably solved by one simple(r)? solution. Can someone set me straight?

- another intruder with the mooring in the heart of the Perl

Replies are listed 'Best First'.
Re: Building a simple service scanner with POE
by ikegami (Patriarch) on Sep 09, 2005 at 15:45 UTC
Re: Building a simple service scanner with POE
by johnnywang (Priest) on Sep 09, 2005 at 18:05 UTC
    Since you only want the connection status, you probably should use the POE::Wheel::SocketFactory instead of the component (which is built on top of SocketFactory). Something like the following:( not tested, not even syntax)
    use strict; use POE; use POE::Wheel::SocketFactory; my $task = [ { name => 'www.example.com', proto => 'tcp', port => 80 }, { name => 'smtp.example.com', proto => 'tcp', port => 25 }, { name => 'ns.example.com', proto => 'udp', port => 53 }, ]; for my $t( @$task ) { POE::Wheel::SocketFactory->new( RemoteAddress => $t->{host}, RemotePort => $t->{port}, SocketProtocol => $t->{proto}, SuccessEvent => sub { print "$t->{host}:$t->{proto}:$t->{port} up\n"; $poe_kernel->yield( 'shutdown' ); }, FailureEvent => sub { print "$t->{host}:$t->{proto}:$t->{por +t} down\n" }, ); } $poe_kernel->run();
Re: Building a simple service scanner with POE
by jch341277 (Sexton) on Sep 09, 2005 at 16:00 UTC

      That would require farming tasks out to subprocesses and getting the information back again. Work, work, work.

      And to get the answers back in more or less constant time would require spawning a lot of kids. I don't want to go down that path. With POE, it all takes place in the one process.

      - another intruder with the mooring in the heart of the Perl

Re: Building a simple service scanner with POE
by Akhasha (Scribe) on Sep 13, 2005 at 05:23 UTC
    I'm guessing there is no PoCo::Client::UDP because raw UDP is a stateless protocol and my understanding of POE::Components is that they track protocol state for you.