使用Net :: SMPP作为ESME Receiver的套接字超时

时间:2011-08-19 16:28:04

标签: perl sockets

我有一个简单的脚本应该绑定到SMSC并侦听传入的消息。我遇到的问题是,如果它没有收到任何消息,它会超时。

这是脚本:

#!/usr/bin/perl

use Net::SMPP;
use Data::Dumper;
$Net::SMPP::trace = 1;

$smpp = Net::SMPP->new_receiver('--removed--',
                                port => '--removed--',
                                system_id => '--removed--',
                                password => '--removed--',
                                ) or die;

while (1)
{       
    $pdu = $smpp->read_pdu() or die;

    print "Received #$pdu->{seq} $pdu->{cmd}:". Net::SMPP::pdu_tab->{$pdu->{cmd}}{cmd} ."\n";
    print "From: $pdu->{source_addr}\nTo: $pdu->{destination_addr}\nData: $pdu->{data}\n";
    print "Messsage: $pdu->{short_message}\n\n";
}

这是我得到的错误:

premature eof reading from socket at /usr/lib/perl5/site_perl/5.8.8/Net/SMPP.pm line 2424.
$VAR1 = undef;

这是SMPP.pm的相关子目录:

sub read_hard {
    my ($me, $len, $dr, $offset) = @_;
    while (length($$dr) < $len+$offset) {
        my $n = length($$dr) - $offset;
        eval {
            local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
            alarm ${*$me}{enquire_interval} if ${*$me}{enquire_interval};
            warn "read $n/$len enqint(${*$me}{enquire_interval})" if $trace>1;
            while (1) {
                $n = $me->sysread($$dr, $len-$n, $n+$offset);
                next if $! =~ /^Interrupted/;
                last;
            }
            alarm 0;
        };
        if ($@) {
            warn "ENQUIRE $@" if $trace;
            die unless $@ eq "alarm\n";   # propagate unexpected errors
            $me->enquire_link();   # Send a periodic ping
        } else {
            if (!defined($n)) {
                warn "error reading header from socket: $!";
                ${*$me}{smpperror} = "read_hard I/O error: $!";
                ${*$me}{smpperrorcode} = 1;
                return undef;
            }
            #if ($n == 0) { last; }
            if (!$n) {
                warn "premature eof reading from socket";
                ${*$me}{smpperror} = "read_hard premature eof";
                ${*$me}{smpperrorcode} = 2;
                return undef;
                #return 0;
            }
        }
    }
    #warn "read complete";
    return 1;
}

在sub中,它命中的if语句是$ n为0或undef的语句。

我的猜测是套接字超时并断开连接。我怎样才能无限期地保持聆听者?

此外,这个监听器在等待pdu时阻塞。有没有办法不停地听?

我是一名电信工程师,负责编程,我已经查看了所有可以找到但未找到答案的材料。

3 个答案:

答案 0 :(得分:1)

看起来好像sysread()调用只返回0.如果已知连接状态已断开,则只能执行此操作。由于你的一方没有断开或超时,我会推断远程端断开连接。如果您身边发生超时,则无法看到premature eof...消息。

所以,你已经'无限期地保持监听器',因为你没有设置enquire_interval选项。

关于'有没有一种方法可以无阻塞地监听?'description section最后描述了异步模式:Module can also be used asynchronously by specifying async=>1 to the constructor。您必须自己实施数据轮询。

答案 1 :(得分:0)

您是否尝试为查询链接(SMPP ping)超时设置参数?

在你的new_receiver上,验证是否存在“enquire_interval”参数并将其设置为15秒,例如......

我尝试过new_transceiver()方法,但它确实有效。

my $smpp = Net::SMPP->new_transceiver(
    $self->host,
    port              => $self->port,
    system_id         => $self->user,
    password          => $self->password,
    smpp_version      => $self->version,
    interface_version => $self->interface_version,
    enquire_interval  => $self->timeout,
    addr_ton        => $self->addr_ton,
    addr_npi        => $self->addr_npi,
    source_addr     => $self->source_addr,
    source_addr_ton => $self->source_addr_ton,
    source_addr_npi => $self->source_addr_npi,
    dest_addr_ton   => $self->dest_addr_ton,
    dest_addr_npi   => $self->dest_addr_npi,
    system_type     => $self->system_type,
    facilities_mask => $self->facilities_mask
) or die "Could not connect to $self->host: $!";

It(Net :: SMPP)自动处理查询链接。

答案 2 :(得分:-1)

我也收到了提前终止的相同错误。

对于阻塞,您可以fork或thread另一个进程,并且两者都可以并行运行。阻止无法绕过。