package My::Telnet; use threads::shared; use Net::Telnet; ## Thread to keep session alive sub _keepAlive { my( $tn, $done, $keepAlive ) = @_; ## Die when signalled ## Wake up once per second while( not $done and sleep 1 ) { ## If it's time, send the keep alive cmd. if( time() >= $keepAlive ) { my @output = $tn->cmd( ## Keep alive command goes here ); ## and reset the timeout $keepAlive = time() + 30; } } } sub new { my( $class, $host, $port ) = @_; ## Create the session my $tn = Net::Telnet->new( host => $host, port => port, errmode => sub{ warn "Error: $_[ 0 ]"; }, ) or die $!; ## Some shared vars for communication my $done :shared = 0; my $keepAlive :shared = time() + 30; ## Start the thread. my $thread = threads->create( \&_keepAlive, $tn, $done, $keepAlive } or die $!; ## build the object and return it bless { done => \$done, telnet => $tn, host => $host, port => $port, thread => $thread, keepAlive => \$keepAlive; }, $class; } ## resets the timer to the time supplied ## or now + 30 seconds sub resetKeepAlive { my( $self, $timeout ) = @_; $$self->{ keepAlive } } = $timeout || ( time() + 30 ); } ## Issues a command ## Resetting the timer to prevent the next keep alive. sub cmd { my( $self, %cmdNargs ) = @_; ## reset the timer *before* issuing the command $self->resetKeepAlive; ## Do the command and return the output return $self->{ telnet }->cmd( %cmdNargs ) } ## Clean up by telling the thread to die ## waiting for it to do so ## and closing the connection. sub DESTROY { my( $self ) = @_; $$self->{ done } = 1; $self->{ thread }->join; close $self->{ telnet }; return; }