use strict; use warnings; # perl snmp_server.pl | wc -l use Time::HiRes qw( sleep time ); use Net::SNMPTrapd; use MCE::Hobo; use MCE::Shared; my $queue = MCE::Shared->queue( await => 1, fast => 1 ); my $start = 0; # construct two shared handles, prevents garbled output # consumers send output to the shared-manager process mce_open my $outfh, '>>', \*STDOUT; mce_open my $errfh, '>>', \*STDERR; MCE::Hobo->create(\&consumer) for 1 .. 30; listener(); MCE::Hobo->waitall(); printf {$errfh} "duration : %0.03f seconds\n", time - $start; exit(0); sub listener { my $snmptrapd = Net::SNMPTrapd->new( ReusePort => 1 ); my $count = 0; while ( 1 ) { my $trap = $snmptrapd->get_trap(); if ( !defined $trap ) { printf {$errfh} "$0: %s\n", Net::SNMPTrapd->error(); next; } elsif ( $trap == 0 ) { next; } $start = time() unless $start; # important, remove the file handle inside the object delete $trap->{_UDPSERVER_}; # enqueue the trap for a consumer to process $queue->enqueue($trap); # leave the loop after 10,000 traps last if ( ++$count >= 10000 ); # reset the counter to not overflow $count = 0 if ( $count > 2e9 ); } $queue->end(); printf {$errfh} "enqueue : %0.03f seconds\n", time - $start; printf {$errfh} "pending : %d\n", $queue->pending(); } sub consumer { while ( defined ( my $trap = $queue->dequeue() ) ) { $trap->process_trap(); printf {$outfh} "[$$] %s\t%i\t%i\t%s\n", $trap->remoteaddr, $trap->remoteport, $trap->version, $trap->community; sleep 0.004; } }