2011-08-19 77 views
1

我有一个简单的脚本,该脚本应绑定到SMSC并侦听传入的消息。我遇到的问题是,如果它没有收到任何消息,它会超时。使用Net :: SMPP作为ESME接收器的套接字超时

下面是脚本:

#!/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 ([email protected]) { 
      warn "ENQUIRE [email protected]" if $trace; 
      die unless [email protected] 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时阻塞。有没有阻止听的方法?

我是一名电信工程师,他负责编程,我已经浏览了所有可找到的资料,但找不到答案。

回答

1

它看起来好像sysread()调用只是返回0.它只能这样做,如果已知连接状态断开连接。既然你的方面没有断开或超时,我会推断远程方断开。如果在您身边发生超时,您应该无法看到消息premature eof...

因此,您已经'无限期地保持收听者',因为您没有设置enquire_interval选项。

关于'有没有办法在没有阻塞的情况下听取?'description section最后描述了异步模式:Module can also be used asynchronously by specifying async=>1 to the constructor。你必须自己实现数据轮询。

+1

我试过了一个异步实现,但当没有数据通过线路时它仍然超时。 – Alo

+0

我所做的是捕捉错误并重新连接。即使我仍然看到eof错误,它仍然有效。有没有更优雅的做法? – Alo

-1

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

对于阻塞,您可以对另一个进程进行fork或线程并且两者都可以并行运行。没有办法阻止。

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: $!"; 

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

+0

也许这会帮助:[Net :: SMPP#Misc.Notes](https://metacpan.org/pod/Net::SMPP#MISC.-NOTES) – eddy85br