我有一个简单的脚本应该绑定到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时阻塞。有没有办法不停地听?
我是一名电信工程师,负责编程,我已经查看了所有可以找到但未找到答案的材料。
答案 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另一个进程,并且两者都可以并行运行。阻止无法绕过。