Perl Telnet会话处理程序

时间:2011-02-04 14:46:33

标签: perl sockets unix telnet

我有一个应用程序,可以根据需要连接到我们网络中的各种设备,执行多个命令,解析输出并通过AJAX / JSON / Perl向用户报告。在Perl中,我使用 NET :: Telnet / :: Cisco ,以及通过生成子进程并将其传递给 NET ::偶尔进行SSH连接远程登录

我希望通过创建一种telnet会话持有者来增强应用程序,该持有者将在打开一段时间后保持连接,或者直到超时为止。我们的想法是减少重新连接到这些设备,并允许其他请求使用之前创建的telnet会话(假设它未使用且仍处于活动状态)。

我开始使用 IO :: Socket :: UNIX 编写perl文件,并且能够存储没有问题的连接,基本上另一个文件将使用创建的套接字来访问或创建新的联系。我遇到的问题是:如果有两个请求同时命中该套接字,那么首先进入该套接字将导致第二个请求必须等待第一个请求进行处理。

我开始尝试使用线程,但如果我这样做,我就无法将 NET :: Telnet对象传递回原始/父线程。< / p>

有没有人对如何做到这一点有任何想法?可能有一个应用程序可以作为我可以与之交互的会话持有者吗?

更新

我根据一位评论者的建议使用了POE,虽然这部分是我正在寻找的,但它不允许“服务器”同时为多个连接提供服务。

方案: 两个用户点击前端的“发送”而不是靠近。用户A的查询首先到达服务器,但他们正在尝试连接到需要很长时间才能响应的设备。因此,用户B必须等到用户A的连接建立之后才开始用户B的请求。基本上

,我需要能够使用连接池为同时请求提供服务而不会为其他任何人造成延迟,因为首先到达那里的人正试图连接到那个懒人设备..

下面是我的代码,如果我这样做,将在后台运行。打印件用于我的调试。

#!/usr/bin/perl -w

use strict;
use JSON;
use Net::Telnet;
use IO::Socket::UNIX qw( SOCK_STREAM SOMAXCONN );

my $socketPath = '/tmp/telnetproxy';
unlink($socketPath);

my $listener = IO::Socket::UNIX->new(
    Type   => SOCK_STREAM,
    Local  => $socketPath,
    Listen => SOMAXCONN) 
    or die ("Cannot create server socket: $!\n");

my $clientNum = 0;

our $json = JSON->new->allow_nonref;
our $conns = {};

print "Server Initiated...\n";

while (1) {

    print " - Inside while loop...\n";

    my $socket = $listener->accept();

    connectToDevice(++ $clientNum, $socket);

}

sub connectToDevice {
    my $connectionNum = shift;
    my $socket = shift;

    print " - Inside 'connectToDevice'\n";

    print " - Connection #$connectionNum started...\n";

    my $input;
    my $connId = 0;
    my (@argsRaw, $args, @argHold);
    my $numOfConnections = keys %$conns;

    my $deviceProperties = {
        ipAddress => undef,
        username  => undef,
        password  => undef,
        method    => 'telnet'
    };

    print " - waiting for input...\n";

    # Receive input for arguments.
    chomp( $input = <$socket> );

    print " - input received...\n";

    ## Turn string into a HASHREF
    $args = from_json($input);

    foreach (keys %$args) {
        print "\t$connectionNum: $_ => $args->{$_}\n";
        if (/^host$/i) { #---- Host IP given ($self->{_hostIp{
            if (verifyIp($args->{$_})) {
                $deviceProperties->{ipAddress} = $args->{$_};
            } else {

            }
        }
         elsif (/^method$/i) { # Ckt type... very important for how we ts
            $deviceProperties->{method} = $args->{$_};
        }
         elsif (/^(username|user|u)$/i) { # username to log in with
            $deviceProperties->{username} = $args->{$_};
        }
         elsif (/^(password|pass|p)$/i) { # password
            $deviceProperties->{password} = $args->{$_};
        }
    }

    print " - Num of connections: $numOfConnections\n";

    if ($numOfConnections > 0) {
        ## Look through existing connections
        ##  1) If we have an available connection, use it
        ##  2) If not, create a new connection.
        print " - Checking existing connections...\n";
        foreach my $connKey ( keys %$conns ) {
            if ($conns->{$connKey}->{host} eq $deviceProperties->{ipAddress} && $conns->{$connKey}->{locked} == 0 && testConnection($connKey)) {
                $connId = $connKey;
                print "\tconnection #$connKey... VALID, using it\n";
                last;
            } else {
                print "\tconnection #$connKey... not valid\n";
            }
        }
    } else {
        print " - No existing connections, creating a new one ...\n";
    }

    if ($connId == 0) {

        $connId = $connectionNum;

        $conns->{$connectionNum} = {
            host   => $deviceProperties->{ipAddress},
            locked => 1
        };

        $conns->{$connectionNum}->{conn} = connectToHost($deviceProperties, "blab_$connectionNum");
        print " - Created a new connection, a suitable existing connection was not found.\n";
    }

    print " - Waiting for command.. ";

    chomp( my $line = <$socket> );

    print "DONE\n";

    my @out = $conns->{$connId}->{conn}->cmd($line);

    print " - Sent '$line' to device\n";

    my $numOfLines = @out;

    print " - $numOfLines lines retrieved\n";

    $conns->{$connId}->{locked} = 0;

    print " - This run done....\n\n";

    return;
}

sub testConnection {
    my $connectionNum = shift;

    print " -- Testing connection $connectionNum:  ";

    my @out = $conns->{$connectionNum}->{conn}->cmd(String => '!', Timeout => 2);

    print "[";
    print @out;
    print "]";

    if (@out > 0) {
        print " ---- Good\n";
        return 1;
    } else {
        delete $conns->{$connectionNum};
        print " ---- No good\n";
        return 0;
    }
}

2 个答案:

答案 0 :(得分:0)

听起来您需要使用ResourcePool来完成此任务。只需在池中创建所需的对象数量,然后使用get并自由使用它们并将它们放回池中。

答案 1 :(得分:0)

我已经开始使用POE服务器架构,以及产生子/子进程来处理各个连接。它可能不是做我想要的最漂亮/最好/最有效的方式,但它完成了工作并且具有不同的狭窄目的。

感谢大家的帮助。

相关问题